Re: [hyperledger/fabric] Remove chaincode instance variables from example chaincodes (#1981)
Brian Behlendorf <bbehlendorf@...>
So I've been following the firehose from watching the github issues (feeling foolish for not looking there before) and am loving all the activity. I am concerned, though, that sometimes important architectural conversations get buried in a message that only crazy people like me, and those working specifically on the code in question, are likely to see. The below is an example (not to pick on anyone in particular). Follow the link at the bottom for the full thread. I know there is corresponding conversation going on in the Slack channel too, especially when there's some disagreement. But I'm wondering if devs could do a better job of surfacing architecture and deeper implementation conversation & thinking to this list from time to time, like the topic below, as a way to tap into the broader Fabric dev community for what people think, as well as help folks following along start to get into the rhythm of how the code works. Thoughts?
Oh, this also reminds me of one of Karl Fogel's best pieces of advice, something he and others did on the Subversion project. When there were triaged bugs that we unresolved, but were assessed by developers as likely to not require siginificant rearchitecture of the code to solve, but instead are more likely a simple error, then those issues were marked as "bite-sized", a signal to new developers that they may want to use these issues as a good learning experience while the older hands on the project were focused on the harder issues. Thought on that too?
-------- Forwarded Message --------
I would agree that in general, simple example chaincodes should not use persistent state. However, even though there was a bug in the busywork chaincode that caused unexpected non-determinism, I'm not sure I'm ready to banish chaincode-local state for chaincodes that are specifically designed as test programs. For example, one of the planned future capabilities for busywork was to allow non-deterministic error injection, which would make use of chaincode-local state. (A single chaincode instance is passed information via a query targeting its peer, and on the next invoke that chaincode instance stores a random or know-bad value, for example.)
There may also be optimizations for test programs (or even non test programs?) that require some knowledge of what is expected in the state, and perhaps cause information to be reloaded from the state when is there is a mismatch.I was actually planning to add something like this in the next busywork chaincode I've been thinking about. This chaincode loads a very large data structure and its version number when the chaincode starts. On each invoke, it compares the latest version number (8 bytes) from the state with its own cached version number, and only reloads the large state if they disagree. Obviously the version number is also updated whenever the large state is modified (which will be a rare event).
In general, in Go anyway, I don't think you can stop anyone from storing data in a package-global variable, and then accessing the variable, even if you make each chaincode invocation a newly-created object. It is certainly unacceptable to take the drastic step to reload the chaincode package binary every time the chaincode is invoked (assuming Go supported that, which I don't think it does currently). There is also the file system, network devices, and other ways to store and access persistent data. Unless we go to a domain-specific language.