I created simple monitor to check a contract and its latest transactions. I know I can get this information by getting latest block like:
block = await this.web3.eth.getBlock("latest");
and later on check if receiver is the same as contract that I am monitoring.
But I would like to get history of that contract for example last 24 hours and see what transactions were made there. Is it possible to do that and if yes how can I achieve that?
You can specify a specific block number instead of the "latest" parameter - extract the number of the last block at some point and then iteratively reduce it by one until the desired depth of history is reached.
However, it would be more efficient to write an application that would read new blocks in resident mode as they appear on the network and write them to some database - in this case, the user could get information much faster and to an arbitrary depth.
At the same time, we must not forget to track possible forks with the cancellation of the corresponding transactions.
I tried to see the problem MVCC with hyperledger fabric but the problem that when I invoke transaction that modifies and reads the same variable with the same key it works.
What are the changes to make to highlight MVCC?
What are the changes to make to highlight MVCC?
MVCC stands for Multi Value Concurrency Control, this is well know approach to enable optimistic update mechanism which allow to prevent concurrent modifications of the same key. In Fabric context concurrent modification would be transactions which grouped into same block and modifies same key. Therefore in order to experience MVCC failure it's not enough to modify same key several times, you also need to make sure all those transactions will be batched to the same block.
The easiest way to achieve it is to throw as much as possible tx updates to increase probability of transactions to be places into same block.
AFAIK part of block verification is checking that it contains valid previous block hash. But let's imagine, that for some reason (network glitch etc.) previous block never arrived. Wouldn't node discard all the following blocks?
I wonder how this problem is solved? Does node periodically checks whole chain, by requesting peers? How exactly is this implemented?
Thanks!
I'm assuming you're not talking about mining. So:
A node will ask for block number N before asking for block N+1. Yes, mostly block N+1 will be discarded if block number N doesn't exist, but that's irrelevant. Because it's not that a node gets blocks only by being the receiving end. It can contact all the other nodes around it, and ask for block number N. If all these nodes don't have block number N, well, then it doesn't exist!
Notice that on a broader scale every node asks its peers for node number N, and verifies that this block follows the rules of the protocol. That's part of the consensus.
If we're talking about mining, the situation is different. You can imagine two competing miners creating blocks. If a miner doesn't have block N, he'll keep trying to mine that block. If he receives block number N after having mined it, the miner just ignores it, and we have a temporary fork in the blockchain with two branches, and block N+1 will have two different versions. Now what determines which branch survives is basically the branch that is mined faster. An arbitrary consensus rule is that the longer chain is always the correct chain. When a longer chain exists, all miners agree that this chain is the correct one.
The reason why this works, is because the probability of mining a block is wide enough over 10 minutes in Bitcoin (or block time in general).
The following image can be seen as the probability of mining a block over time (in bitcoin).
This is why it's wrong to create blockchains with very short time. Because if the time is very short (like 10 seconds), there will be tons of forks before the blockchain stabilizes.
for loose endorsement policy, for same transaction, even if correct-behavior committers, different committer maybe have different validation result due to their different world state.
And how do commiter know who's validation result is correct(major) or wrong(minor) ?
Hint: at a moment, due to network delay, correct commiter may have different world state.
thanks for answer.
I have got it!
because each correct commiter receive block/transaction in exactly same order, and implement same endorsement policy, so that at same transaction's validation moment, all correct commiter indeed have exactly same world state, despite at not same time!
key point is :
(1) at same moment, different commiters may have different world state due to network delay, etc;
(2) but, different commiter do validation for same transaction at not same moment.
After enrolling, installing and instantiating the chaincode fabric/example/chaincode/go/chaincode_example02, I run the following steps.
peer chaincode instantiate --orderer orderer0:7050 --tls true --path example02 --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem --chainID mychannel --name example02cc --version 1.0 --ctor '{"Args":["init","A","1000","B","2000"]}'
peer chaincode query --chainID mychannel --name example02cc --ctor '{"Args":["query","A"]}'
peer chaincode query --chainID mychannel --name example02cc --ctor '{"Args":["query","B"]}'
So far, I confirm that A is equal to 1000 and B is equal to 2000. Afterwards, The result will be variable if I invoke the following step with different timings.
peer chaincode invoke --orderer orderer0:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem --chainID mychannel --name example02cc --ctor '{"Args":["invoke","A","B","1"]}'
Specifically, A will be equal to 998 and B will be equal to 2002 if I run the previous step twice with a 10 second pause. A will be equal to 990 and B will be equal to 2010 if I run the previous step ten times with 10 second pause between every step. However, without any pause, A will be equal to 999 and B will be equal to 2001 if I run the previous step twice. A will be equal to 999 and B will be equal to 2001 if I run the previous step ten times without pause between every step.
I have tested several times with different arguments. Furthermore, I have tested other chaincodes. It seems like that the chaincode only accept the first invoking request, and discards subsequent invoking requests. So, the questions are:
Is this a mechanism to prevent double-spending? or just a weakness?
How to solve this problem which limits the transaction rate.
I think that chaincode should support concurrent invocations. Can chaincode support concurrent invocations actually?
Can a single chaincode invoke multiple requests in a single block period?
The chaincode need to do endorsement and then commit it the ledger state before the next invoke.
When you call peer chaincode invoke ..., fabric response quickly after the endorsement has finished. But the commit will still take some time. If you run the second invoke directly after the first invoke, the second invoke will be endorse correctly, but no commit happened.
So, for your questions:
You can try to invoke chaincode by java-sdk or node-sdk. take the javasdk for example, the progress is first send transactionProposalRequest to chaincode, which is the endorsement process in fabric. And after the endorsement is finished, and your endorment policy is correctly passed. the transaction is send to fabirc by sdk-client, this API will return an CompletableFuture<BlockEvent.TransactionEvent>, which is similar to the Promise in js. when the transaction is done, the CompletableFuture.thenApply() is triggled. You may check the src/test/java/org.hyperledger.fabric.sdkintergration/End2endIT.java for example.
You may write a batch in your chaincode. This can support multiple invoke and query at once, it solves your question in some degree. The batch is designed as follow, new a m map[string]string and toDelete []string in your cc, when invoke put your key/val pairs in m, and when query get key/val from m first, if not found, query from stub, and when delete requirement, delete from m and put the key to toDelete , after all requirements are finished, commit all data in m and toDelete at once. I tried this mechanism in my project, it work good.
blockchain is designed not for high concurrent. It is designed for confidentiality, scalability and security.
see 2
From the point of view of fabric this is actually normal behavior - although may seem a bit counterintuitive first.
What you see happening follows logically from the documented transaction flow (+ knowing that there is some batching performed on the orderer with batch-timeouts). Let us assume that during simulation (endorsement), variable A is read and then marked for re-setting by the chaincode simulation. What value was read and what value you want the variable set to become part of the proposed transaction (+ whether endorsers accept the transaction + crypto-stuff). Then we go through submission to orderer + distribution to channel peers + channel peers checking (among others) whether the original "read value assumptions" of the proposal still hold. (See 5.: Validation on the referenced peers.) If the value of A has changed "since simulation", then the transaction will not be valid.
The impact of timing on this is the following. If there is enough "leeway" between two invokes, the following happens:
Call1 - Proposal created with original A value
Call1 proposal gets endorsements, sent to orderer, gets batched
After some time, peers get the ordered-endorsed Tx from the orderer, check it, find it fine, the value of A is modified (committed to the Ledger) as requested
Call2 - Proposal created with new A value read etc.
The crucial thing is that what happens if you create and submit the second proposal before the effects of the first would have been committed to the Ledger. (So without "waiting enough".)
Call2 simulation still sees the original A value, endorsements are computed based on that
This is bundled into the "read values" property of the transaction
By the time it reaches the channel peers for committing, the value of A has been already modified by Call1
Thus, this transaction will be invalid and have no effect on the ledger
Such effects are not exactly new, we did get bitten by similar stuff with fabric 0.6. Fortunately, there are a few "clean" ways out of this; I suggest to read up on "tokenization" in the Blockchain context. In the context of example02, you can make all "units" have a GUID and track essentially ownership vectors; or you can go full-UTXO, Bitcoin style. Option b) can be to write the Tx requests themselves into the Ledger (Tx1:+20, Tx2: -40, Tx3: +65, ...) and base the comuptation of "current acccount state" on Ledger-stored Tx logs, although this can get a bit messy.
And do note that massive (and painless) concurrency is eminently possible, as long as the "working sets" of Tx requests do not overlap much. For many domains, this is possible; e.g. for a cryptocurrency, it is not the same currency unit that is being passed around like hot potatoes, but a large set of currency units having many transactions, but levelled out across them.
On your specific questions:
see far above
see the two suggestions above
Depends on what you mean by concurrent invocation, but at the heart of the fabric 1.0 architecture is that a full ordering is set up on all endorsed requests and this ordering is enforced during validation and Ledger update. Massive amounts of peers requesting things concurrently - sure; "reentrant chaincode" - no-no-no.
Chaincodes don't "invoke requests". If you mean whether a single chaincode can have multiple transactions in a single block: sure, e.g. selling 100 different cars using a "sell_cars" chaincode.