github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/ledger/kvledger/example/main/example.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "os" 22 23 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 24 "github.com/hyperledger/fabric/core/ledger" 25 "github.com/hyperledger/fabric/core/ledger/kvledger/example" 26 "github.com/hyperledger/fabric/core/ledger/ledgerconfig" 27 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 28 "github.com/hyperledger/fabric/core/ledger/testutil" 29 "github.com/hyperledger/fabric/core/ledger/util" 30 "github.com/hyperledger/fabric/protos/common" 31 logging "github.com/op/go-logging" 32 ) 33 34 var logger = logging.MustGetLogger("main") 35 36 const ( 37 ledgerID = "Default" 38 ) 39 40 var peerLedger ledger.PeerLedger 41 var app *example.App 42 var committer *example.Committer 43 var consenter *example.Consenter 44 45 var accounts = []string{"account1", "account2", "account3", "account4"} 46 47 func init() { 48 49 //call a helper method to load the core.yaml 50 testutil.SetupCoreYAMLConfig() 51 52 // Initialization will get a handle to the ledger at the specified path 53 // Note, if subledgers are supported in the future, 54 // the various ledgers could be created/managed at this level 55 cleanup() 56 ledgermgmt.Initialize() 57 var err error 58 59 gb, _ := configtxtest.MakeGenesisBlock(ledgerID) 60 peerLedger, err = ledgermgmt.CreateLedger(gb) 61 if err != nil { 62 panic(fmt.Errorf("Error in NewKVLedger(): %s", err)) 63 } 64 app = example.ConstructAppInstance(peerLedger) 65 committer = example.ConstructCommitter(peerLedger) 66 consenter = example.ConstructConsenter() 67 } 68 69 func main() { 70 defer ledgermgmt.Close() 71 72 // Each of the functions here will emulate endorser, orderer, 73 // and committer by calling ledger APIs to similate the proposal, 74 // get simulation results, create a transaction, add it to a block, 75 // and then commit the block. 76 77 // Initialize account balances by setting each account to 100 78 initApp() 79 80 printBalances() 81 82 // Transfer money between accounts. Exercises happy path. 83 transferFunds() 84 85 printBalances() 86 87 // Attempt to transfer more money than account balance 88 // Exercises simulation failure 89 tryInvalidTransfer() 90 91 // Attempt two transactions, the first one will have sufficient funds, 92 // the second one should fail since the account balance was updated 93 // (by the first tran) since simulation time. This exercises the MVCC check. 94 tryDoubleSpend() 95 96 printBalances() 97 } 98 99 func initApp() { 100 logger.Debug("Entering initApp()") 101 tx, err := app.Init(map[string]int{ 102 accounts[0]: 100, 103 accounts[1]: 100, 104 accounts[2]: 100, 105 accounts[3]: 100}) 106 handleError(err, true) 107 rawBlock := consenter.ConstructBlock(tx) 108 err = committer.Commit(rawBlock) 109 handleError(err, true) 110 printBlocksInfo(rawBlock) 111 logger.Debug("Exiting initApp()") 112 } 113 114 func transferFunds() { 115 logger.Debug("Entering transferFunds()") 116 tx1, err := app.TransferFunds("account1", "account2", 50) 117 handleError(err, true) 118 tx2, err := app.TransferFunds("account3", "account4", 50) 119 handleError(err, true) 120 121 // act as ordering service (consenter) to create a Raw Block from the Transaction 122 rawBlock := consenter.ConstructBlock(tx1, tx2) 123 124 // act as committing peer to commit the Raw Block 125 err = committer.Commit(rawBlock) 126 handleError(err, true) 127 printBlocksInfo(rawBlock) 128 logger.Debug("Exiting transferFunds") 129 } 130 131 func tryInvalidTransfer() { 132 logger.Debug("Entering tryInvalidTransfer()") 133 _, err := app.TransferFunds("account1", "account2", 60) 134 handleError(err, false) 135 logger.Debug("Exiting tryInvalidTransfer()") 136 } 137 138 func tryDoubleSpend() { 139 logger.Debug("Entering tryDoubleSpend()") 140 tx1, err := app.TransferFunds("account1", "account2", 50) 141 handleError(err, true) 142 tx2, err := app.TransferFunds("account1", "account4", 50) 143 handleError(err, true) 144 rawBlock := consenter.ConstructBlock(tx1, tx2) 145 err = committer.Commit(rawBlock) 146 handleError(err, true) 147 printBlocksInfo(rawBlock) 148 logger.Debug("Exiting tryDoubleSpend()") 149 } 150 151 func printBlocksInfo(block *common.Block) { 152 logger.Debug("Entering printBlocksInfo()") 153 // Read invalid transactions filter 154 txsFltr := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 155 numOfInvalid := 0 156 // Count how many transaction indeed invalid 157 for i := 0; i < len(block.Data.Data); i++ { 158 if txsFltr.IsInvalid(i) { 159 numOfInvalid++ 160 } 161 } 162 fmt.Printf("Num txs in rawBlock = [%d], num invalidTxs = [%d]\n", 163 len(block.Data.Data), numOfInvalid) 164 logger.Debug("Exiting printBlocksInfo()") 165 } 166 167 func printBalances() { 168 logger.Debug("Entering printBalances()") 169 balances, err := app.QueryBalances(accounts) 170 handleError(err, true) 171 for i := 0; i < len(accounts); i++ { 172 fmt.Printf("[%s] = [%d]\n", accounts[i], balances[i]) 173 } 174 logger.Debug("Exiting printBalances()") 175 } 176 177 func handleError(err error, quit bool) { 178 if err != nil { 179 if quit { 180 panic(fmt.Errorf("Error: %s\n", err)) 181 } else { 182 fmt.Printf("Error: %s\n", err) 183 } 184 } 185 } 186 187 func cleanup() { 188 ledgerRootPath := ledgerconfig.GetRootPath() 189 os.RemoveAll(ledgerRootPath) 190 }