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  }