Given that Hyperledger Fabric's chaincode needs to be deterministic because it's being executed on all validating peers (Are blocks mined in HyperLedger Fabric?), how would one get a unique ID so I can 'InsertRow' with a unique value.
For example, if I execute my code to append a new record to the table, I'd need a unique key. If I get a GUID on Validating Peer 1 (vp1), it would be a different key if I got a GUID on Validating Peer 2 (vp2). The same if I used milliseconds as a key.
Is there a way I can get a deterministic unique ID in chaincode from within the chaincode rather than passing it in from the 'client'?
I would be inclined to implement this as a monotonically increasing sequence variable stored in putstate along side your table. IOW, initialize something like PutState("nextsequence", 0) in your Init() function, and then RMW that any time you need a new id. The RMW mutation will be implicitly coupled to your row insert, and should be deterministic across all instances.
If the ID should be generated by the chaincode, then a monotonically increasing counter it a good solution. If the ID should be chosen by the tx generating app, you should enforce the rule the ID's can't reused and encourage the protocol the tx generator uses to select collision resistant ids.
Related
Since chaincode has to be deterministic, is there any way to get same random number in all endorser nodes to implement something like a lottery? In Ethereum you can do something like that:
function random() private view returns (uint) {
return uint(keccak256(abi.encodePacked(block.difficulty, now, players)));
}
By using the blocknumber, timestampt, block difficulty, gas , etc...But you dont have that in Hyperledger Fabric.
You're quite correct that the deterministic nature of chaincode does cause issues with random numbers.
I'd look into doing this in one of two ways.
You need to pass in the random number (or at least a seed) as part of the transaction request. You might want to send this in transient data so that's not recorded on the ledger.
Pre-store the random numbers. i.e. generate a massive table of random numbers and put those into the ledger in some form of setup transaction. Maybe even into the private data collections. Work along those each time you need a number using a counter.
You can protect access to the set of generated numbers by various type of access control.
We can use the timestamp passed by proposer of transaction as the seed.
Usage: stub.GetTxTimestamp()
// GetTxTimestamp returns the timestamp when the transaction was created. This
// is taken from the transaction ChannelHeader, therefore it will indicate the
// client's timestamp and will have the same value across all endorsers.
GetTxTimestamp() (*timestamp.Timestamp, error)
I read
https://hyperledger-fabric.readthedocs.io/en/release-2.0/private-data/private-data.html says that
"A hash of that data, which is endorsed, ordered, and written to the ledgers of every peer on the channel. The hash serves as evidence of the transaction and is used for state validation and can be used for audit purposes." .
However, I think signatures of the transaction is enough for evidence that contract was agreed upon.
Why hash of the data should be shared among the every peers?
Private transactions are not stored in blocks in the chain like public transactions. All the peers joined to the channel share the same channel chain. Thus, if the private transaction were stored normally in the chain, every peer (even those from organizations to which the transaction is not destined) could read the private transaction parameters (and reconstruct the others' private state). To avoid this, basically, a hash is stored in the block in its place so that the organizations which share the private data can still check integrity.
EDIT:
Let's see, if you read carefully https://hyperledger-fabric.readthedocs.io/en/release-2.0/private-data/private-data.html#transaction-flow-with-private-data, you'll see that at no time is the private data signed (neither the readset, nor the writeset, nor the input, nor the output). In step 3 a signature is produced only over its hash (embedded in the transaction). Nothing else. The private data (the data, not the transaction) is simply distributed via gossip protocol and stored temporally in the transient data store (point 2), to be committed in point 5. The only evidence on the private data is the hash (which is embedded in the transaction and signed). The gossip protocol has its security mechanisms, but it does not produce evidence or guarantee the transaction order.
Now, take the case where, later, a malicious organization unilaterally alters its private state in order to obtain some kind of benefit. That hash in the chain would be the only evidence left to resolve the dispute with other organizations. There is no other evidence on the agreed valid value (and the execution order) than that hash. No plain text private data was signed by the peer.
That's the way it is at Fabric. And it makes sense. Keep in mind that it is necessary to guarantee the integrity of the data and the order in which the transactions are executed, so at some point the orderer (point 4) has to be involved to determine the order (in most cases the order of the transactions does alter the product) without disclosing the real data.
What I feel is that, when only signature is shared, how does other peers validate what the signature is for? Or vice versa, how to validate whether it is actually being signed by the claimed owner? So, we share hash of the transaction + signature of that hash. This signature now can be verified using public certificate of that owner. Also, as the transaction is hashed, it remains private but the ledger (blocks chained to one another) is identical among all peers.
Chaincode that executes range or rich JSON queries and updates data in
a single transaction is not supported, as the query results cannot be
validated on the peers that don’t have access to the private data, or
on peers that are missing the private data that they have access to.
If a chaincode invocation both queries and updates private data, the
proposal request will return an error. If your application can
tolerate result set changes between chaincode execution and
validation/commit time, then you could call one chaincode function to
perform the query, and then call a second chaincode function to make
the updates. Note that calls to GetPrivateData() to retrieve
individual keys can be made in the same transaction as
PutPrivateData() calls, since all peers can validate key reads based
on the hashed key version.
Find Link Here
I came across this small paragraph related to limitation of querying Private Data in fabric. I am pretty much new to private data concept.
What I understood is as follow,
CC invocation requiring
Range or rich JSON queries AND update both, to private data causes proposal to return error.
It's better to, call one chaincode function to perform the query, and then call a second chaincode function to make the updates
Normally, GetPrivateData() to retrieve individual keys can be made in the same transaction as PutPrivateData() calls, since all peers can validate key reads based on the hashed key version.
Is my understanding correct ?
If yes then why is it so for private data?
If no then please give me wisdom.
So, first of all - rich queries are never re-executed upon commit anyway, be it private data or not private data.
Now, as for range queries - remember that range queries are all about the assumption that keys have an alphabetical order between them.
However, a transaction needs to pass MVCC checks regardless of the peer has the private data or not, but if the peer doesn't have the private data then it only sees hashes, (not the real key names) and hashes are not sorted alphabetically - hence it cannot validate that the range query simulation is not stale.
I was reading the documentation of hyperledger fabric. In the transaction flow page I found this line
The chaincode (containing a set of key value pairs representing
the initial state of the radish market) is installed on the peers and
instantiated on the channel.
This line confused me. I think it is the definition of ledger .But here it is written as chaincode.
Is my perception correct ?
Can anyone explain me ?
Chaincode (or the more commonly-known term smart-contract) defines a set of business models, transaction definitions and logics which the application (SDK) could utilize to create transactions.
For the sentence you show above, this does not refer to the definition of the chaincode. I believe it merely conveys the idea that a list of radishes (in key and value pair) has been defined in the chaincode already, so once it is instantiated (or a initRadish function, if it exists in the chaincode is being called), that list of radishes will become part of the world state in the ledger.
How ledger and chaincode relate in Fabric?
Ledger consists of two components, namely world state and blockchain. World state stores the latest values of the key, whereas the blockchain stores all the transaction log that leads to the world state.
As I said above, chaincode defines the transaction logics in terms of functions such that the application could call to create transaction, which triggers state transition or state retrieval.
For example, you have a function called buyRadish(radishID, newOwner) defined in the chaincode. Suppose there is a radish with key R1001 with value {"owner": FarmerA, "status": OnSale}. This is the key-value pair before any transaction occurs. Once the function in the chaincode is invoked with the argument radishID = R1001, newOwner = Ken, a transaction is created and the state of radish with key R1001 will become {"owner": Ken, "status": Sold}. Note that this latest state of the radish will be seen at the world state.
With the example above, you can think in this way:
The ledger stores the latest key-value pairs (or to be precise latest value of the key). The chaincode may have some key-value pairs for initialization purpose; however, the point is that we are passing a new set of key-value pairs (radishID = R1001, newOwner = Ken) as argument to the function in chaincode, so as to update the values of the same key (radishID = R1001) in the world state of the ledger.
Hope it helps.
A chaincode is programmatic code deployed on the network, where it is executed and validated by chain validators together during the consensus process. Developers can use chaincodes to develop business contracts, asset definitions, and collectively-managed decentralized applications.
more about chaincode click here
How ledger and chaincode relate in Fabric?
Chaincode is a program (smart contract) that is written to read and update the ledger state.
In a Hyperledger Fabric network, ledgers which all peers(endorsing peers and committing peers) have are replicated ledgers.
It seems to imply there is a unique 'real/original/genuine' ledger per channel.
I'd like to ask these:
Is there a real ledger? If so, where is it(or where is it defined?) and who owns it?
Those replicated ledgers are updated by each peer, after VSCC, MVCC validation. Then who updates the 'real' ledger?
Does 'World State' only refers to the 'real' ledger?
I'd really appreciate if you answer my questions.
Please tell me if these questions are clarified to you. Thank you!
I don't understand what exactly you mean by 'real' ledger. There is one & only ledger per channel, replicated across all participants per channel. When I say participants, I mean all peers (both endorsing & committing) of an organization's MSP belonging to a given channel.
State DB (a.k.a World state) refers to the database that maintains the current value of a given key. Let me give you an example. You know that a blockchain is a liked list on steroids (with added security, immutability, etc). Say, you have a key A with value 100 in Block 1. You transact in the following manner.
Block 2 -- A := A-10
Block 15 -- A := A-12
.
.
.
Block 10,000 -- A := A-3
So, after Block 10,000, if you need the current value of key A, you have to calculate the value from Block 1. So to manage this efficiently, Fabric folks implemented a state database that updates the value of a key in the state after every transaction. It's sole responsibility is to improve efficiency. If your state gets corrupted, Fabric will automatically rebuild it from Block 0.