// 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 }
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) }) It("should return uncommitted state from memory", func() { state, _ := ledgerPtr.GetState("chaincode1", "key1", false) Expect(state).To(Equal([]byte("value1"))) state, _ = ledgerPtr.GetState("chaincode2", "key2", false) Expect(state).To(Equal([]byte("value2"))) state, _ = ledgerPtr.GetState("chaincode3", "key3", false) Expect(state).To(Equal([]byte("value3"))) }) It("should not return committed state", func() { state, _ := ledgerPtr.GetState("chaincode1", "key1", true)
// 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 }