//ExecuteTransactions - will execute transactions on the array one by one //will return an array of errors one for each transaction. If the execution //succeeded, array element will be nil. returns []byte of state hash or //error func ExecuteTransactions(ctxt context.Context, cname ChainName, xacts []*pb.Transaction) (succeededTXs []*pb.Transaction, stateHash []byte, ccevents []*pb.ChaincodeEvent, txerrs []error, err error) { var chain = GetChain(cname) if chain == nil { // TODO: We should never get here, but otherwise a good reminder to better handle panic(fmt.Sprintf("[ExecuteTransactions]Chain %s not found\n", cname)) } txerrs = make([]error, len(xacts)) ccevents = make([]*pb.ChaincodeEvent, len(xacts)) var succeededTxs = make([]*pb.Transaction, 0) for i, t := range xacts { _, ccevents[i], txerrs[i] = Execute(ctxt, chain, t) if txerrs[i] == nil { succeededTxs = append(succeededTxs, t) } } var lgr *ledger.Ledger lgr, err = ledger.GetLedger() if err == nil { stateHash, err = lgr.GetTempStateHash() } return succeededTxs, stateHash, ccevents, txerrs, err }
"github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger/statemgmt" "github.com/hyperledger/fabric/core/util" "github.com/hyperledger/fabric/protos" ) func appendAll(content ...[]byte) []byte { combinedContent := []byte{} for _, b := range content { combinedContent = append(combinedContent, b...) } return combinedContent } var _ = Describe("Ledger", func() { var ledgerPtr *ledger.Ledger SetupTestConfig() Context("Ledger with preexisting uncommitted state", func() { BeforeEach(func() { ledgerPtr = InitSpec() Expect(ledgerPtr.BeginTxBatch(1)).To(BeNil()) ledgerPtr.TxBegin("txUuid") Expect(ledgerPtr.SetState("chaincode1", "key1", []byte("value1"))).To(BeNil()) Expect(ledgerPtr.SetState("chaincode2", "key2", []byte("value2"))).To(BeNil()) Expect(ledgerPtr.SetState("chaincode3", "key3", []byte("value3"))).To(BeNil()) ledgerPtr.TxFinished("txUuid", true) })
func markTxFinish(ledger *ledger.Ledger, t *pb.Transaction, successful bool) { if t.Type == pb.Transaction_CHAINCODE_QUERY { return } ledger.TxFinished(t.Uuid, successful) }
func markTxBegin(ledger *ledger.Ledger, t *pb.Transaction) { if t.Type == pb.Transaction_CHAINCODE_QUERY { return } ledger.TxBegin(t.Uuid) }
// buildTestLedger2 builds a simple ledger data structure that contains a blockchain // of 5 blocks, with each block containing the same number of transactions as its // index within the blockchain. Block 0, 0 transactions. Block 1, 1 transaction, // and so on. func buildTestLedger2(ledger *ledger.Ledger, t *testing.T) { // -----------------------------<Block #0>--------------------- // Add the 0th (genesis block) ledger.BeginTxBatch(0) ledger.CommitTxBatch(0, []*protos.Transaction{}, nil, []byte("dummy-proof")) // -----------------------------<Block #0>--------------------- // -----------------------------<Block #1>------------------------------------ // Deploy a contract // To deploy a contract, we call the 'NewContract' function in the 'Contracts' contract // TODO Use chaincode instead of contract? // TODO Two types of transactions. Execute transaction, deploy/delete/update contract ledger.BeginTxBatch(1) transaction1a, err := protos.NewTransaction(protos.ChaincodeID{Path: "Contracts"}, generateUUID(t), "NewContract", []string{"name: MyContract1, code: var x; function setX(json) {x = json.x}}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } // VM runs transaction1a and updates the global state with the result // In this case, the 'Contracts' contract stores 'MyContract1' in its state ledger.TxBegin(transaction1a.Txid) ledger.SetState("MyContract1", "code", []byte("code example")) ledger.TxFinished(transaction1a.Txid, true) ledger.CommitTxBatch(1, []*protos.Transaction{transaction1a}, nil, []byte("dummy-proof")) // -----------------------------</Block #1>----------------------------------- // -----------------------------<Block #2>------------------------------------ ledger.BeginTxBatch(2) transaction2a, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyContract"}, generateUUID(t), "setX", []string{"{x: \"hello\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } transaction2b, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyOtherContract"}, generateUUID(t), "setY", []string{"{y: \"goodbuy\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } // Run this transction in the VM. The VM updates the state ledger.TxBegin(transaction2a.Txid) ledger.SetState("MyContract", "x", []byte("hello")) ledger.SetState("MyOtherContract", "y", []byte("goodbuy")) ledger.TxFinished(transaction2a.Txid, true) // Commit txbatch that creates the 2nd block on blockchain ledger.CommitTxBatch(2, []*protos.Transaction{transaction2a, transaction2b}, nil, []byte("dummy-proof")) // -----------------------------</Block #2>----------------------------------- // -----------------------------<Block #3>------------------------------------ ledger.BeginTxBatch(3) transaction3a, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyContract"}, generateUUID(t), "setX", []string{"{x: \"hello\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } transaction3b, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyOtherContract"}, generateUUID(t), "setY", []string{"{y: \"goodbuy\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } transaction3c, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyImportantContract"}, generateUUID(t), "setZ", []string{"{z: \"super\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } ledger.TxBegin(transaction3a.Txid) ledger.SetState("MyContract", "x", []byte("hello")) ledger.SetState("MyOtherContract", "y", []byte("goodbuy")) ledger.SetState("MyImportantContract", "z", []byte("super")) ledger.TxFinished(transaction3a.Txid, true) ledger.CommitTxBatch(3, []*protos.Transaction{transaction3a, transaction3b, transaction3c}, nil, []byte("dummy-proof")) // -----------------------------</Block #3>----------------------------------- // -----------------------------<Block #4>------------------------------------ ledger.BeginTxBatch(4) // Now we want to run the function 'setX' in 'MyContract // Create a transaction' transaction4a, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyContract"}, generateUUID(t), "setX", []string{"{x: \"hello\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } transaction4b, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyOtherContract"}, generateUUID(t), "setY", []string{"{y: \"goodbuy\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } transaction4c, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyImportantContract"}, generateUUID(t), "setZ", []string{"{z: \"super\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } transaction4d, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyMEGAContract"}, generateUUID(t), "setMEGA", []string{"{mega: \"MEGA\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } // Run this transction in the VM. The VM updates the state ledger.TxBegin(transaction4a.Txid) ledger.SetState("MyContract", "x", []byte("hello")) ledger.SetState("MyOtherContract", "y", []byte("goodbuy")) ledger.SetState("MyImportantContract", "z", []byte("super")) ledger.SetState("MyMEGAContract", "mega", []byte("MEGA")) ledger.TxFinished(transaction4a.Txid, true) // Create the 4th block and add it to the chain ledger.CommitTxBatch(4, []*protos.Transaction{transaction4a, transaction4b, transaction4c, transaction4d}, nil, []byte("dummy-proof")) // -----------------------------</Block #4>----------------------------------- return }
// buildTestLedger1 builds a simple ledger data structure that contains a blockchain with 3 blocks. func buildTestLedger1(ledger1 *ledger.Ledger, t *testing.T) { // -----------------------------<Block #0>--------------------- // Add the 0th (genesis block) ledger1.BeginTxBatch(0) err := ledger1.CommitTxBatch(0, []*protos.Transaction{}, nil, []byte("dummy-proof")) if err != nil { t.Fatalf("Error in commit: %s", err) } // -----------------------------<Block #0>--------------------- // -----------------------------<Block #1>------------------------------------ // Deploy a contract // To deploy a contract, we call the 'NewContract' function in the 'Contracts' contract // TODO Use chaincode instead of contract? // TODO Two types of transactions. Execute transaction, deploy/delete/update contract ledger1.BeginTxBatch(1) transaction1a, err := protos.NewTransaction(protos.ChaincodeID{Path: "Contracts"}, generateUUID(t), "NewContract", []string{"name: MyContract1, code: var x; function setX(json) {x = json.x}}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } // VM runs transaction1a and updates the global state with the result // In this case, the 'Contracts' contract stores 'MyContract1' in its state ledger1.TxBegin(transaction1a.Txid) ledger1.SetState("MyContract1", "code", []byte("code example")) ledger1.TxFinished(transaction1a.Txid, true) ledger1.CommitTxBatch(1, []*protos.Transaction{transaction1a}, nil, []byte("dummy-proof")) // -----------------------------</Block #1>----------------------------------- // -----------------------------<Block #2>------------------------------------ ledger1.BeginTxBatch(2) transaction2a, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyContract"}, generateUUID(t), "setX", []string{"{x: \"hello\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } transaction2b, err := protos.NewTransaction(protos.ChaincodeID{Path: "MyOtherContract"}, generateUUID(t), "setY", []string{"{y: \"goodbuy\"}"}) if err != nil { t.Logf("Error creating NewTransaction: %s", err) t.Fail() } // Run this transction in the VM. The VM updates the state ledger1.TxBegin(transaction2a.Txid) ledger1.SetState("MyContract", "x", []byte("hello")) ledger1.SetState("MyOtherContract", "y", []byte("goodbuy")) ledger1.TxFinished(transaction2a.Txid, true) // Commit txbatch that creates the 2nd block on blockchain ledger1.CommitTxBatch(2, []*protos.Transaction{transaction2a, transaction2b}, nil, []byte("dummy-proof")) // -----------------------------</Block #2>----------------------------------- return }