From 5a3755419f2ba1408f3c1d627f166194adeac71a Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Wed, 21 Nov 2018 11:43:30 -0800 Subject: [PATCH 1/4] Add more functionalities to worker --- node/node.go | 2 ++ node/worker/worker.go | 55 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/node/node.go b/node/node.go index 8cf72dd2d..0c5346a83 100644 --- a/node/node.go +++ b/node/node.go @@ -8,6 +8,7 @@ import ( "github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" + "github.com/harmony-one/harmony/node/worker" "net" "sync" "time" @@ -58,6 +59,7 @@ type Node struct { Chain *core.BlockChain TxPool *core.TxPool BlockChannelAccount chan *types.Block // The channel to receive new blocks from Node + worker *worker.Worker } // Add new crossTx and proofs to the list of crossTx that needs to be sent back to client diff --git a/node/worker/worker.go b/node/worker/worker.go index e4448aec9..bb4070d3f 100644 --- a/node/worker/worker.go +++ b/node/worker/worker.go @@ -7,14 +7,13 @@ import ( "github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" + "math/big" + "time" ) // environment is the worker's current environment and holds all of the current state information. type environment struct { - signer types.Signer - state *state.StateDB // apply state changes here - tcount int // tx count in cycle gasPool *core.GasPool // available gas used to pack transactions header *types.Header @@ -24,13 +23,16 @@ type environment struct { // worker is the main object which takes care of submitting new work to consensus engine // and gathering the sealing result. -type worker struct { +type Worker struct { config *params.ChainConfig chain *core.BlockChain current *environment // An environment for current running cycle. + + gasFloor uint64 + gasCeil uint64 } -func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) { +func (w *Worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) { snap := w.current.state.Snapshot() receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, vm.Config{}) @@ -43,3 +45,46 @@ func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Addres return receipt.Logs, nil } + +func (w *Worker) CommitTransactions(txs []*types.Transaction, coinbase common.Address) { + for _, tx := range txs { + w.commitTransaction(tx, coinbase) + } +} + +// makeCurrent creates a new environment for the current cycle. +func (w *Worker) makeCurrent(parent *types.Block, header *types.Header) error { + state, err := w.chain.StateAt(parent.Root()) + if err != nil { + return err + } + env := &environment{ + state: state, + header: header, + } + + w.current = env + return nil +} + +func New(config *params.ChainConfig, chain *core.BlockChain) *Worker { + worker := &Worker{ + config: config, + chain: chain, + } + worker.gasFloor = 0 + worker.gasCeil = 10000000 + + parent := worker.chain.CurrentBlock() + num := parent.Number() + timestamp := time.Now().Unix() + header := &types.Header{ + ParentHash: parent.Hash(), + Number: num.Add(num, common.Big1), + GasLimit: core.CalcGasLimit(parent, worker.gasFloor, worker.gasCeil), + Time: big.NewInt(timestamp), + } + worker.makeCurrent(parent, header) + + return worker +} \ No newline at end of file From e143e6fea81b8d5f1be797c73325fff495bd75ca Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Wed, 21 Nov 2018 12:00:52 -0800 Subject: [PATCH 2/4] Simulate random transactions and add to the worker --- node/node.go | 14 +++++++++++++- node/node_handler.go | 12 +++++++++++- node/worker/worker.go | 12 ++++++------ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/node/node.go b/node/node.go index 0c5346a83..82906b38b 100644 --- a/node/node.go +++ b/node/node.go @@ -2,13 +2,16 @@ package node import ( "bytes" + "crypto/ecdsa" "encoding/gob" "fmt" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/node/worker" + "math/big" "net" "sync" "time" @@ -60,6 +63,9 @@ type Node struct { TxPool *core.TxPool BlockChannelAccount chan *types.Block // The channel to receive new blocks from Node worker *worker.Worker + + // Test only + testBankKey *ecdsa.PrivateKey } // Add new crossTx and proofs to the list of crossTx that needs to be sent back to client @@ -207,8 +213,14 @@ func New(consensus *bft.Consensus, db *hdb.LDBDatabase) *Node { node.db = db // (account model) + + node.testBankKey, _ = crypto.GenerateKey() + testBankAddress := crypto.PubkeyToAddress(node.testBankKey.PublicKey) + testBankFunds := big.NewInt(1000000000000000000) database := hdb.NewMemDatabase() - gspec := core.Genesis{} + gspec := core.Genesis{ + Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}, + } genesis := gspec.MustCommit(database) fmt.Println(genesis.Root()) diff --git a/node/node_handler.go b/node/node_handler.go index 6ac3ea1ef..4d34a1800 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -5,7 +5,10 @@ import ( "bytes" "encoding/gob" "fmt" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/harmony-one/harmony/core/types" + "math/big" "net" "os" "strconv" @@ -364,7 +367,6 @@ func (node *Node) WaitForConsensusReadyAccount(readySignal chan struct{}) { timeoutCount := 0 for { // keep waiting for Consensus ready retry := false - // TODO(minhdoan, rj): Refactor by sending signal in channel instead of waiting for 10 seconds. select { case <-readySignal: time.Sleep(100 * time.Millisecond) // Delay a bit so validator is catched up. @@ -378,6 +380,14 @@ func (node *Node) WaitForConsensusReadyAccount(readySignal chan struct{}) { if !retry { // Normal tx block consensus // TODO: add new block generation logic + txs := make([]*types.Transaction, 100) + for i, _ := range txs { + randomUserKey, _ := crypto.GenerateKey() + randomUserAddress := crypto.PubkeyToAddress(randomUserKey.PublicKey) + tx, _ := types.SignTx(types.NewTransaction(0, randomUserAddress, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, node.testBankKey) + txs[i] = tx + } + node.worker.CommitTransactions(txs, crypto.PubkeyToAddress(node.testBankKey.PublicKey)) } // Send the new block to Consensus so it can be confirmed. diff --git a/node/worker/worker.go b/node/worker/worker.go index bb4070d3f..3d8523044 100644 --- a/node/worker/worker.go +++ b/node/worker/worker.go @@ -59,8 +59,8 @@ func (w *Worker) makeCurrent(parent *types.Block, header *types.Header) error { return err } env := &environment{ - state: state, - header: header, + state: state, + header: header, } w.current = env @@ -69,12 +69,12 @@ func (w *Worker) makeCurrent(parent *types.Block, header *types.Header) error { func New(config *params.ChainConfig, chain *core.BlockChain) *Worker { worker := &Worker{ - config: config, - chain: chain, + config: config, + chain: chain, } worker.gasFloor = 0 worker.gasCeil = 10000000 - + parent := worker.chain.CurrentBlock() num := parent.Number() timestamp := time.Now().Unix() @@ -87,4 +87,4 @@ func New(config *params.ChainConfig, chain *core.BlockChain) *Worker { worker.makeCurrent(parent, header) return worker -} \ No newline at end of file +} From b7db989f00b2a20105fbd07344771480b8c1ed3b Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Wed, 21 Nov 2018 16:14:12 -0800 Subject: [PATCH 3/4] Add simulated transactions generation in node_handler --- consensus/bft.go | 8 ++++---- consensus/consensus_engine.go | 2 +- core/block_validator.go | 3 --- core/chain_makers.go | 2 +- core/genesis.go | 2 +- core/rawdb/accessors_indexes_test.go | 2 +- core/state_processor.go | 2 +- core/tx_pool_test.go | 2 +- core/types/block.go | 14 ++------------ harmony/main.go | 25 +++++++++++++++++++++++-- node/node.go | 1 + node/node_handler.go | 3 ++- node/worker/worker.go | 23 ++++++++++++++++++++++- transactions.rlp | Bin 0 -> 297 bytes 14 files changed, 60 insertions(+), 29 deletions(-) diff --git a/consensus/bft.go b/consensus/bft.go index 3b4ea01fd..dad81f8c4 100644 --- a/consensus/bft.go +++ b/consensus/bft.go @@ -76,12 +76,12 @@ func (bft *Bft) Prepare(chain ChainReader, header *types.Header) error { // Finalize implements consensus.Engine, accumulating the block and uncle rewards, // setting the final state and assembling the block. -func (bft *Bft) Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +func (bft *Bft) Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, receipts []*types.Receipt) (*types.Block, error) { // Accumulate any block and uncle rewards and commit the final state root // Header seems complete, assemble into a block and return - accumulateRewards(chain.Config(), state, header, uncles) + accumulateRewards(chain.Config(), state, header) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) - return types.NewBlock(header, txs, uncles, receipts), nil + return types.NewBlock(header, txs, receipts), nil } // SealHash returns the hash of a block prior to it being sealed. @@ -114,6 +114,6 @@ func (bft *Bft) Seal(chain ChainReader, block *types.Block, results chan<- *type // AccumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // included uncles. The coinbase of each uncle block is also rewarded. -func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { +func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header) { } diff --git a/consensus/consensus_engine.go b/consensus/consensus_engine.go index 19c3adfd9..05fc56619 100644 --- a/consensus/consensus_engine.go +++ b/consensus/consensus_engine.go @@ -60,7 +60,7 @@ type Engine interface { // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) + receipts []*types.Receipt) (*types.Block, error) // Seal generates a new sealing request for the given input block and pushes // the result into the given channel. diff --git a/core/block_validator.go b/core/block_validator.go index 67016488c..84022261b 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -64,9 +64,6 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { //if err := v.engine.VerifyUncles(v.bc, block); err != nil { // return err //} - if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash { - return fmt.Errorf("uncle root hash mismatch: have %x, want %x", hash, header.UncleHash) - } if hash := types.DeriveSha(block.Transactions()); hash != header.TxHash { return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash) } diff --git a/core/chain_makers.go b/core/chain_makers.go index bad401b60..928010494 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -184,7 +184,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse } if b.engine != nil { // Finalize and seal the block - block, _ := b.engine.Finalize(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts) + block, _ := b.engine.Finalize(chainreader, b.header, statedb, b.txs, b.receipts) // Write state changes to db root, err := statedb.Commit(config.IsEIP158(b.header.Number)) diff --git a/core/genesis.go b/core/genesis.go index 3087d01ce..e03323a6f 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -254,7 +254,7 @@ func (g *Genesis) ToBlock(db hdb.Database) *types.Block { statedb.Commit(false) statedb.Database().TrieDB().Commit(root, true) - return types.NewBlock(head, nil, nil, nil) + return types.NewBlock(head, nil, nil) } // Commit writes the block and state of a genesis specification to the database. diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go index 4be8f660f..51d90bd4b 100644 --- a/core/rawdb/accessors_indexes_test.go +++ b/core/rawdb/accessors_indexes_test.go @@ -34,7 +34,7 @@ func TestLookupStorage(t *testing.T) { tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}) txs := []*types.Transaction{tx1, tx2, tx3} - block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil) + block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil) // Check that no transactions entries are in a pristine database for i, tx := range txs { diff --git a/core/state_processor.go b/core/state_processor.go index 6f9776129..5564fa977 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -75,7 +75,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg allLogs = append(allLogs, receipt.Logs...) } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts) + p.engine.Finalize(p.bc, header, statedb, block.Transactions(), receipts) return receipts, allLogs, *usedGas, nil } diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 5d81d0674..edfd2b170 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -53,7 +53,7 @@ type testBlockChain struct { func (bc *testBlockChain) CurrentBlock() *types.Block { return types.NewBlock(&types.Header{ GasLimit: bc.gasLimit, - }, nil, nil, nil) + }, nil, nil) } func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { diff --git a/core/types/block.go b/core/types/block.go index 8a21bba1e..14e22686a 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -176,9 +176,9 @@ type storageblock struct { // block. // // The values of TxHash, UncleHash, ReceiptHash and Bloom in header -// are ignored and set to values derived from the given txs, uncles +// are ignored and set to values derived from the given txs, // and receipts. -func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt) *Block { +func NewBlock(header *Header, txs []*Transaction, receipts []*Receipt) *Block { b := &Block{header: CopyHeader(header), td: new(big.Int)} // TODO: panic if len(txs) != len(receipts) @@ -197,16 +197,6 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []* b.header.Bloom = CreateBloom(receipts) } - if len(uncles) == 0 { - b.header.UncleHash = EmptyUncleHash - } else { - b.header.UncleHash = CalcUncleHash(uncles) - b.uncles = make([]*Header, len(uncles)) - for i := range uncles { - b.uncles[i] = CopyHeader(uncles[i]) - } - } - return b } diff --git a/harmony/main.go b/harmony/main.go index e39fd04f7..cdc8b0211 100644 --- a/harmony/main.go +++ b/harmony/main.go @@ -9,6 +9,7 @@ import ( "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/db" + "github.com/harmony-one/harmony/node/worker" "math/big" ) @@ -56,7 +57,7 @@ func main() { ) genesis := gspec.MustCommit(database) - + _ = genesis chain, _ := core.NewBlockChain(database, nil, gspec.Config, consensus.NewFaker(), vm.Config{}, nil) txpool := core.NewTxPool(core.DefaultTxPoolConfig, chainConfig, chain) @@ -68,7 +69,7 @@ func main() { } backend.txPool.AddLocals(pendingTxs) - // Generate a small n-block chain and an uncle block for it + //// Generate a small n-block chain and an uncle block for it n := 3 if n > 0 { blocks, _ := core.GenerateChain(chainConfig, genesis, consensus.NewFaker(), database, n, func(i int, gen *core.BlockGen) { @@ -79,4 +80,24 @@ func main() { fmt.Errorf("failed to insert origin chain: %v", err) } } + + fmt.Println(chain.GetBlockByNumber(1).Root()) + fmt.Println(chain.GetBlockByNumber(2).Root()) + fmt.Println(chain.GetBlockByNumber(3).Root()) + txs := make([]*types.Transaction, 100) + worker := worker.New(params.TestChainConfig, chain, consensus.NewFaker()) + fmt.Println(worker.GetCurrentState().GetBalance(testBankAddress)) + fmt.Println(worker.Commit().Root()) + + for i, _ := range txs { + randomUserKey, _ := crypto.GenerateKey() + randomUserAddress := crypto.PubkeyToAddress(randomUserKey.PublicKey) + tx, _ := types.SignTx(types.NewTransaction(worker.GetCurrentState().GetNonce(crypto.PubkeyToAddress(testBankKey.PublicKey)), randomUserAddress, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey) + txs[i] = tx + } + + worker.CommitTransactions(txs, crypto.PubkeyToAddress(testBankKey.PublicKey)) + + fmt.Println(worker.GetCurrentState().GetBalance(testBankAddress)) + fmt.Println(worker.Commit().Root()) } diff --git a/node/node.go b/node/node.go index 82906b38b..37fc116fe 100644 --- a/node/node.go +++ b/node/node.go @@ -229,6 +229,7 @@ func New(consensus *bft.Consensus, db *hdb.LDBDatabase) *Node { node.Chain = chain node.TxPool = core.NewTxPool(core.DefaultTxPoolConfig, params.TestChainConfig, chain) node.BlockChannelAccount = make(chan *types.Block) + node.worker = worker.New(params.TestChainConfig, chain, bft.NewFaker()) } // Logger diff --git a/node/node_handler.go b/node/node_handler.go index 4d34a1800..c6b20c79e 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -384,10 +384,11 @@ func (node *Node) WaitForConsensusReadyAccount(readySignal chan struct{}) { for i, _ := range txs { randomUserKey, _ := crypto.GenerateKey() randomUserAddress := crypto.PubkeyToAddress(randomUserKey.PublicKey) - tx, _ := types.SignTx(types.NewTransaction(0, randomUserAddress, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, node.testBankKey) + tx, _ := types.SignTx(types.NewTransaction(node.worker.GetCurrentState().GetNonce(crypto.PubkeyToAddress(node.testBankKey.PublicKey)), randomUserAddress, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, node.testBankKey) txs[i] = tx } node.worker.CommitTransactions(txs, crypto.PubkeyToAddress(node.testBankKey.PublicKey)) + newBlock = node.worker.Commit() } // Send the new block to Consensus so it can be confirmed. diff --git a/node/worker/worker.go b/node/worker/worker.go index 3d8523044..87b0a32c6 100644 --- a/node/worker/worker.go +++ b/node/worker/worker.go @@ -3,6 +3,7 @@ package worker import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" + "github.com/harmony-one/harmony/consensus" "github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/types" @@ -28,6 +29,8 @@ type Worker struct { chain *core.BlockChain current *environment // An environment for current running cycle. + engine consensus.Engine + gasFloor uint64 gasCeil uint64 } @@ -47,6 +50,10 @@ func (w *Worker) commitTransaction(tx *types.Transaction, coinbase common.Addres } func (w *Worker) CommitTransactions(txs []*types.Transaction, coinbase common.Address) { + if w.current.gasPool == nil { + w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit) + } + for _, tx := range txs { w.commitTransaction(tx, coinbase) } @@ -67,10 +74,24 @@ func (w *Worker) makeCurrent(parent *types.Block, header *types.Header) error { return nil } -func New(config *params.ChainConfig, chain *core.BlockChain) *Worker { +func (w *Worker) GetCurrentState() *state.StateDB { + return w.current.state +} + +func (w *Worker) Commit() *types.Block { + s := w.current.state.Copy() + block, err := w.engine.Finalize(w.chain, w.current.header, s, w.current.txs, w.current.receipts) + if err != nil { + return nil + } + return block +} + +func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus.Engine) *Worker { worker := &Worker{ config: config, chain: chain, + engine: engine, } worker.gasFloor = 0 worker.gasCeil = 10000000 diff --git a/transactions.rlp b/transactions.rlp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a929e39e8d5fdcc0d36465d7bd91ca436f898cae 100755 GIT binary patch literal 297 zcmey7*wD}v#4%;1^tI<(9)D`oXx4AulPVIV$*s)T#QdT`dV!Ggx{FFrURLXx_b~04 zew&xe;98Na+0%bFl(K!U1Vu48^`gp8n(O5-8YswdadPj*x=pZ zx9vwFBVH?H7Ig6*l6HQ7`;&)%gv&D1pSS-tv7D Date: Wed, 21 Nov 2018 18:03:26 -0800 Subject: [PATCH 4/4] integrate account model into consensus without the block verification part --- benchmark.go | 31 +++++++++++++++++++++++-------- blockchain/block.go | 3 +++ client/txgen/main.go | 3 ++- consensus/bft.go | 2 +- consensus/consensus_leader.go | 17 +++++++++++++++++ consensus/consensus_validator.go | 9 +++++---- node/node_handler.go | 9 +++++++++ transactions.rlp | Bin 297 -> 0 bytes 8 files changed, 60 insertions(+), 14 deletions(-) diff --git a/benchmark.go b/benchmark.go index 35322cc1d..4f0e83014 100644 --- a/benchmark.go +++ b/benchmark.go @@ -74,6 +74,7 @@ func loggingInit(logFolder, role, ip, port string, onlyLogTps bool) { } func main() { + accountModel := flag.Bool("account_model", false, "Whether to use account model") // TODO: use http://getmyipaddress.org/ or http://www.get-myip.com/ to retrieve my IP address ip := flag.String("ip", "127.0.0.1", "IP of the node") port := flag.String("port", "9000", "port of the node.") @@ -194,20 +195,34 @@ func main() { // Assign closure functions to the consensus object consensus.BlockVerifier = currentNode.VerifyNewBlock + if *accountModel { + consensus.BlockVerifier = currentNode.VerifyNewBlockAccount + } consensus.OnConsensusDone = currentNode.PostConsensusProcessing // Temporary testing code, to be removed. currentNode.AddTestingAddresses(10000) if consensus.IsLeader { - // Let consensus run - go func() { - consensus.WaitForNewBlock(currentNode.BlockChannel) - }() - // Node waiting for consensus readiness to create new block - go func() { - currentNode.WaitForConsensusReady(consensus.ReadySignal) - }() + if *accountModel { + // Let consensus run + go func() { + consensus.WaitForNewBlockAccount(currentNode.BlockChannelAccount) + }() + // Node waiting for consensus readiness to create new block + go func() { + currentNode.WaitForConsensusReadyAccount(consensus.ReadySignal) + }() + } else { + // Let consensus run + go func() { + consensus.WaitForNewBlock(currentNode.BlockChannel) + }() + // Node waiting for consensus readiness to create new block + go func() { + currentNode.WaitForConsensusReady(consensus.ReadySignal) + }() + } } currentNode.StartServer(*port) diff --git a/blockchain/block.go b/blockchain/block.go index 5e15af014..c55e06bc7 100644 --- a/blockchain/block.go +++ b/blockchain/block.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "encoding/gob" "fmt" + "github.com/harmony-one/harmony/core/types" "log" "time" @@ -27,6 +28,8 @@ type Block struct { // Signature... Bitmap []byte // Contains which validator signed the block. Signature [66]byte // Schnorr collective signature. + + AccountBlock *types.Block // Temporary piggy-back. } // State is used in Block to indicate that block is a state block. diff --git a/client/txgen/main.go b/client/txgen/main.go index 8aecfb7e5..532254b47 100644 --- a/client/txgen/main.go +++ b/client/txgen/main.go @@ -252,7 +252,7 @@ func main() { maxNumTxsPerBatch := flag.Int("max_num_txs_per_batch", 20000, "number of transactions to send per message") logFolder := flag.String("log_folder", "latest", "the folder collecting the logs of this execution") numSubset := flag.Int("numSubset", 3, "the number of subsets of utxos to process separately") - duration := flag.Int("duration", 120, "duration of the tx generation in second. If it's negative, the experiment runs forever.") + duration := flag.Int("duration", 60, "duration of the tx generation in second. If it's negative, the experiment runs forever.") versionFlag := flag.Bool("version", false, "Output version info") crossShardRatio := flag.Int("cross_shard_ratio", 30, "The percentage of cross shard transactions.") flag.Parse() @@ -392,6 +392,7 @@ func main() { msg := proto_node.ConstructStopMessage() peers := append(config.GetValidators(), clientNode.Client.GetLeaders()...) p2p.BroadcastMessage(peers, msg) + time.Sleep(3000 * time.Millisecond) } func SendTxsToLeader(leader p2p.Peer, txs []*blockchain.Transaction) { diff --git a/consensus/bft.go b/consensus/bft.go index dad81f8c4..d8fc9247a 100644 --- a/consensus/bft.go +++ b/consensus/bft.go @@ -80,7 +80,7 @@ func (bft *Bft) Finalize(chain ChainReader, header *types.Header, state *state.S // Accumulate any block and uncle rewards and commit the final state root // Header seems complete, assemble into a block and return accumulateRewards(chain.Config(), state, header) - header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) + header.Root = state.IntermediateRoot(false) return types.NewBlock(header, txs, receipts), nil } diff --git a/consensus/consensus_leader.go b/consensus/consensus_leader.go index 7df244509..f1ecd7647 100644 --- a/consensus/consensus_leader.go +++ b/consensus/consensus_leader.go @@ -6,6 +6,7 @@ import ( "encoding/gob" "encoding/hex" "errors" + "github.com/harmony-one/harmony/core/types" "time" "github.com/harmony-one/harmony/profiler" @@ -46,6 +47,22 @@ func (consensus *Consensus) WaitForNewBlock(blockChannel chan blockchain.Block) } } +// WaitForNewBlock waits for the next new block to run consensus on +func (consensus *Consensus) WaitForNewBlockAccount(blockChannel chan *types.Block) { + consensus.Log.Debug("Waiting for block", "consensus", consensus) + for { // keep waiting for new blocks + newBlock := <-blockChannel + // TODO: think about potential race condition + startTime = time.Now() + consensus.Log.Debug("STARTING CONSENSUS", "consensus", consensus, "startTime", startTime) + for consensus.state == Finished { + // time.Sleep(500 * time.Millisecond) + consensus.startConsensus(&blockchain.Block{Hash: newBlock.Hash(), AccountBlock: newBlock}) + break + } + } +} + // ProcessMessageLeader dispatches consensus message for the leader. func (consensus *Consensus) ProcessMessageLeader(message []byte) { msgType, err := proto_consensus.GetConsensusMessageType(message) diff --git a/consensus/consensus_validator.go b/consensus/consensus_validator.go index 1a5caf6c1..b34ee8384 100644 --- a/consensus/consensus_validator.go +++ b/consensus/consensus_validator.go @@ -109,11 +109,12 @@ func (consensus *Consensus) processAnnounceMessage(payload []byte) { return } + // Temporary disabling this for account model testing // check block hash - if !bytes.Equal(blockHash[:], blockHeaderObj.CalculateBlockHash()[:]) || !bytes.Equal(blockHeaderObj.Hash[:], blockHeaderObj.CalculateBlockHash()[:]) { - consensus.Log.Warn("Block hash doesn't match", "consensus", consensus) - return - } + //if !bytes.Equal(blockHash[:], blockHeaderObj.CalculateBlockHash()[:]) || !bytes.Equal(blockHeaderObj.Hash[:], blockHeaderObj.CalculateBlockHash()[:]) { + // consensus.Log.Warn("Block hash doesn't match", "consensus", consensus) + // return + //} // check block data (transactions if !consensus.BlockVerifier(&blockHeaderObj) { diff --git a/node/node_handler.go b/node/node_handler.go index c6b20c79e..afa0b1639 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -389,6 +389,10 @@ func (node *Node) WaitForConsensusReadyAccount(readySignal chan struct{}) { } node.worker.CommitTransactions(txs, crypto.PubkeyToAddress(node.testBankKey.PublicKey)) newBlock = node.worker.Commit() + + // If not enough transactions to run Consensus, + // periodically check whether we have enough transactions to package into block. + time.Sleep(1 * time.Second) } // Send the new block to Consensus so it can be confirmed. @@ -431,6 +435,11 @@ func (node *Node) VerifyNewBlock(newBlock *blockchain.Block) bool { return node.UtxoPool.VerifyTransactions(newBlock.Transactions) } +// VerifyNewBlock is called by consensus participants to verify the block (account model) they are running consensus on +func (node *Node) VerifyNewBlockAccount(newBlock *blockchain.Block) bool { + return true // TODO: implement the logic +} + // PostConsensusProcessing is called by consensus participants, after consensus is done, to: // 1. add the new block to blockchain // 2. [leader] move cross shard tx and proof to the list where they wait to be sent to the client diff --git a/transactions.rlp b/transactions.rlp index a929e39e8d5fdcc0d36465d7bd91ca436f898cae..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100755 GIT binary patch literal 0 HcmV?d00001 literal 297 zcmey7*wD}v#4%;1^tI<(9)D`oXx4AulPVIV$*s)T#QdT`dV!Ggx{FFrURLXx_b~04 zew&xe;98Na+0%bFl(K!U1Vu48^`gp8n(O5-8YswdadPj*x=pZ zx9vwFBVH?H7Ig6*l6HQ7`;&)%gv&D1pSS-tv7D