From 2a980ec3dcb80c6188225e74ff0912d2b66b95e7 Mon Sep 17 00:00:00 2001 From: Ian Norden Date: Thu, 16 Jan 2020 16:02:12 -0600 Subject: [PATCH] include total difficulty to the payload --- statediff/service.go | 3 + statediff/testhelpers/mocks/api.go | 7 + statediff/testhelpers/mocks/api_test.go | 168 +++++++++++++--------- statediff/testhelpers/mocks/blockchain.go | 19 ++- statediff/types.go | 7 +- 5 files changed, 127 insertions(+), 77 deletions(-) diff --git a/statediff/service.go b/statediff/service.go index dbe8aba8141e..7e8aa52389d2 100644 --- a/statediff/service.go +++ b/statediff/service.go @@ -19,6 +19,7 @@ package statediff import ( "bytes" "fmt" + "math/big" "sync" "sync/atomic" @@ -42,6 +43,7 @@ type blockChain interface { GetBlockByNumber(number uint64) *types.Block AddToStateDiffProcessedCollection(hash common.Hash) GetReceiptsByHash(hash common.Hash) types.Receipts + GetTdByHash(hash common.Hash) *big.Int } // IService is the state-diffing service interface @@ -172,6 +174,7 @@ func (sds *Service) processStateDiff(currentBlock, parentBlock *types.Block) (*P return nil, err } payload.BlockRlp = blockBuff.Bytes() + payload.TotalDifficulty = sds.BlockChain.GetTdByHash(currentBlock.Hash()) receiptBuff := new(bytes.Buffer) receipts := sds.BlockChain.GetReceiptsByHash(currentBlock.Hash()) if err = rlp.Encode(receiptBuff, receipts); err != nil { diff --git a/statediff/testhelpers/mocks/api.go b/statediff/testhelpers/mocks/api.go index 999d82d54374..625f6acc4ee3 100644 --- a/statediff/testhelpers/mocks/api.go +++ b/statediff/testhelpers/mocks/api.go @@ -112,6 +112,13 @@ func (sds *MockStateDiffService) processStateDiff(currentBlock, parentBlock *typ return nil, err } payload.BlockRlp = rlpBuff.Bytes() + payload.TotalDifficulty = sds.BlockChain.GetTdByHash(currentBlock.Hash()) + receiptBuff := new(bytes.Buffer) + receipts := sds.BlockChain.GetReceiptsByHash(currentBlock.Hash()) + if err = rlp.Encode(receiptBuff, receipts); err != nil { + return nil, err + } + payload.ReceiptsRlp = receiptBuff.Bytes() } return &payload, nil } diff --git a/statediff/testhelpers/mocks/api_test.go b/statediff/testhelpers/mocks/api_test.go index 88637269138d..c95712fd644e 100644 --- a/statediff/testhelpers/mocks/api_test.go +++ b/statediff/testhelpers/mocks/api_test.go @@ -32,32 +32,36 @@ import ( "github.com/ethereum/go-ethereum/statediff/testhelpers" ) -var block0, block1 *types.Block -var burnLeafKey = testhelpers.AddressToLeafKey(common.HexToAddress("0x0")) -var emptyAccountDiffEventualMap = make([]statediff.AccountDiff, 0) -var account1, _ = rlp.EncodeToBytes(state.Account{ - Nonce: uint64(0), - Balance: big.NewInt(10000), - CodeHash: common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes(), - Root: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), -}) -var burnAccount1, _ = rlp.EncodeToBytes(state.Account{ - Nonce: uint64(0), - Balance: big.NewInt(2000000000000000000), - CodeHash: common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes(), - Root: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), -}) -var bankAccount1, _ = rlp.EncodeToBytes(state.Account{ - Nonce: uint64(1), - Balance: big.NewInt(testhelpers.TestBankFunds.Int64() - 10000), - CodeHash: common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes(), - Root: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), -}) +var ( + block0, block1 *types.Block + burnLeafKey = testhelpers.AddressToLeafKey(common.HexToAddress("0x0")) + emptyAccountDiffEventualMap = make([]statediff.AccountDiff, 0) + account1, _ = rlp.EncodeToBytes(state.Account{ + Nonce: uint64(0), + Balance: big.NewInt(10000), + CodeHash: common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes(), + Root: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + }) + burnAccount1, _ = rlp.EncodeToBytes(state.Account{ + Nonce: uint64(0), + Balance: big.NewInt(2000000000000000000), + CodeHash: common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes(), + Root: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + }) + bankAccount1, _ = rlp.EncodeToBytes(state.Account{ + Nonce: uint64(1), + Balance: big.NewInt(testhelpers.TestBankFunds.Int64() - 10000), + CodeHash: common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes(), + Root: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + }) + mockTotalDifficulty = big.NewInt(1337) +) func TestAPI(t *testing.T) { testSubscriptionAPI(t) testHTTPAPI(t) } + func testSubscriptionAPI(t *testing.T) { _, blockMap, chain := testhelpers.MakeChain(3, testhelpers.Genesis) defer chain.Stop() @@ -65,30 +69,12 @@ func testSubscriptionAPI(t *testing.T) { block1Hash := common.HexToHash("0xbbe88de60ba33a3f18c0caa37d827bfb70252e19e40a07cd34041696c35ecb1a") block0 = blockMap[block0Hash] block1 = blockMap[block1Hash] - blockChan := make(chan *types.Block) - parentBlockChain := make(chan *types.Block) - serviceQuitChan := make(chan bool) - config := statediff.Config{ - PathsAndProofs: true, - IntermediateNodes: false, - } - mockService := MockStateDiffService{ - Mutex: sync.Mutex{}, - Builder: statediff.NewBuilder(testhelpers.Testdb, chain, config), - BlockChan: blockChan, - ParentBlockChan: parentBlockChain, - QuitChan: serviceQuitChan, - Subscriptions: make(map[rpc.ID]statediff.Subscription), - streamBlock: true, - } - mockService.Start(nil) - id := rpc.NewID() - payloadChan := make(chan statediff.Payload) - quitChan := make(chan bool) - mockService.Subscribe(id, payloadChan, quitChan) - blockChan <- block1 - parentBlockChain <- block0 expectedBlockRlp, _ := rlp.EncodeToBytes(block1) + mockReceipt := &types.Receipt{ + BlockNumber: block1.Number(), + BlockHash: block1.Hash(), + } + expectedReceiptBytes, _ := rlp.EncodeToBytes(types.Receipts{mockReceipt}) expectedStateDiff := statediff.StateDiff{ BlockNumber: block1.Number(), BlockHash: block1.Hash(), @@ -125,20 +111,50 @@ func testSubscriptionAPI(t *testing.T) { }, }, } - expectedStateDiffBytes, err := rlp.EncodeToBytes(expectedStateDiff) - if err != nil { - t.Error(err) + expectedStateDiffBytes, _ := rlp.EncodeToBytes(expectedStateDiff) + blockChan := make(chan *types.Block) + parentBlockChain := make(chan *types.Block) + serviceQuitChan := make(chan bool) + config := statediff.Config{ + PathsAndProofs: true, + IntermediateNodes: false, } - sort.Slice(expectedStateDiffBytes, func(i, j int) bool { return expectedStateDiffBytes[i] < expectedStateDiffBytes[j] }) + mockBlockChain := &BlockChain{} + mockBlockChain.SetReceiptsForHash(block1Hash, types.Receipts{mockReceipt}) + mockBlockChain.SetTdByHash(block1Hash, mockTotalDifficulty) + mockService := MockStateDiffService{ + Mutex: sync.Mutex{}, + Builder: statediff.NewBuilder(testhelpers.Testdb, chain, config), + BlockChan: blockChan, + BlockChain: mockBlockChain, + ParentBlockChan: parentBlockChain, + QuitChan: serviceQuitChan, + Subscriptions: make(map[rpc.ID]statediff.Subscription), + streamBlock: true, + } + mockService.Start(nil) + id := rpc.NewID() + payloadChan := make(chan statediff.Payload) + quitChan := make(chan bool) + mockService.Subscribe(id, payloadChan, quitChan) + blockChan <- block1 + parentBlockChain <- block0 + sort.Slice(expectedStateDiffBytes, func(i, j int) bool { return expectedStateDiffBytes[i] < expectedStateDiffBytes[j] }) select { case payload := <-payloadChan: if !bytes.Equal(payload.BlockRlp, expectedBlockRlp) { - t.Errorf("payload does not have expected block\r\actual block rlp: %v\r\nexpected block rlp: %v", payload.BlockRlp, expectedBlockRlp) + t.Errorf("payload does not have expected block\r\nactual block rlp: %v\r\nexpected block rlp: %v", payload.BlockRlp, expectedBlockRlp) } sort.Slice(payload.StateDiffRlp, func(i, j int) bool { return payload.StateDiffRlp[i] < payload.StateDiffRlp[j] }) if !bytes.Equal(payload.StateDiffRlp, expectedStateDiffBytes) { - t.Errorf("payload does not have expected state diff\r\actual state diff rlp: %v\r\nexpected state diff rlp: %v", payload.StateDiffRlp, expectedStateDiffBytes) + t.Errorf("payload does not have expected state diff\r\nactual state diff rlp: %v\r\nexpected state diff rlp: %v", payload.StateDiffRlp, expectedStateDiffBytes) + } + if !bytes.Equal(expectedReceiptBytes, payload.ReceiptsRlp) { + t.Errorf("payload does not have expected receipts\r\nactual receipt rlp: %v\r\nexpected receipt rlp: %v", payload.ReceiptsRlp, expectedReceiptBytes) + } + if !bytes.Equal(payload.TotalDifficulty.Bytes(), mockTotalDifficulty.Bytes()) { + t.Errorf("payload does not have expected total difficulty\r\nactual td: %d\r\nexpected td: %d", payload.TotalDifficulty.Int64(), mockTotalDifficulty.Int64()) } case <-quitChan: t.Errorf("channel quit before delivering payload") @@ -152,27 +168,12 @@ func testHTTPAPI(t *testing.T) { block1Hash := common.HexToHash("0xbbe88de60ba33a3f18c0caa37d827bfb70252e19e40a07cd34041696c35ecb1a") block0 = blockMap[block0Hash] block1 = blockMap[block1Hash] - config := statediff.Config{ - PathsAndProofs: true, - IntermediateNodes: false, - } - mockBlockChain := &BlockChain{} - mockBlockChain.SetBlocksForHashes(blockMap) - mockBlockChain.SetBlockForNumber(block1, block1.Number().Uint64()) - mockService := MockStateDiffService{ - Mutex: sync.Mutex{}, - Builder: statediff.NewBuilder(testhelpers.Testdb, chain, config), - BlockChain: mockBlockChain, - streamBlock: true, - } - payload, err := mockService.StateDiffAt(block1.Number().Uint64()) - if err != nil { - t.Error(err) - } expectedBlockRlp, _ := rlp.EncodeToBytes(block1) - if !bytes.Equal(payload.BlockRlp, expectedBlockRlp) { - t.Errorf("payload does not have expected block\r\actual block rlp: %v\r\nexpected block rlp: %v", payload.BlockRlp, expectedBlockRlp) + mockReceipt := &types.Receipt{ + BlockNumber: block1.Number(), + BlockHash: block1.Hash(), } + expectedReceiptBytes, _ := rlp.EncodeToBytes(types.Receipts{mockReceipt}) expectedStateDiff := statediff.StateDiff{ BlockNumber: block1.Number(), BlockHash: block1.Hash(), @@ -209,13 +210,38 @@ func testHTTPAPI(t *testing.T) { }, }, } - expectedStateDiffBytes, err := rlp.EncodeToBytes(expectedStateDiff) + expectedStateDiffBytes, _ := rlp.EncodeToBytes(expectedStateDiff) + config := statediff.Config{ + PathsAndProofs: true, + IntermediateNodes: false, + } + mockBlockChain := &BlockChain{} + mockBlockChain.SetBlocksForHashes(blockMap) + mockBlockChain.SetBlockForNumber(block1, block1.Number().Uint64()) + mockBlockChain.SetReceiptsForHash(block1Hash, types.Receipts{mockReceipt}) + mockBlockChain.SetTdByHash(block1Hash, big.NewInt(1337)) + mockService := MockStateDiffService{ + Mutex: sync.Mutex{}, + Builder: statediff.NewBuilder(testhelpers.Testdb, chain, config), + BlockChain: mockBlockChain, + streamBlock: true, + } + payload, err := mockService.StateDiffAt(block1.Number().Uint64()) if err != nil { t.Error(err) } sort.Slice(payload.StateDiffRlp, func(i, j int) bool { return payload.StateDiffRlp[i] < payload.StateDiffRlp[j] }) sort.Slice(expectedStateDiffBytes, func(i, j int) bool { return expectedStateDiffBytes[i] < expectedStateDiffBytes[j] }) + if !bytes.Equal(payload.BlockRlp, expectedBlockRlp) { + t.Errorf("payload does not have expected block\r\nactual block rlp: %v\r\nexpected block rlp: %v", payload.BlockRlp, expectedBlockRlp) + } if !bytes.Equal(payload.StateDiffRlp, expectedStateDiffBytes) { - t.Errorf("payload does not have expected state diff\r\actual state diff rlp: %v\r\nexpected state diff rlp: %v", payload.StateDiffRlp, expectedStateDiffBytes) + t.Errorf("payload does not have expected state diff\r\nactual state diff rlp: %v\r\nexpected state diff rlp: %v", payload.StateDiffRlp, expectedStateDiffBytes) + } + if !bytes.Equal(expectedReceiptBytes, payload.ReceiptsRlp) { + t.Errorf("payload does not have expected receipts\r\nactual receipt rlp: %v\r\nexpected receipt rlp: %v", payload.ReceiptsRlp, expectedReceiptBytes) + } + if !bytes.Equal(payload.TotalDifficulty.Bytes(), mockTotalDifficulty.Bytes()) { + t.Errorf("paylaod does not have the expected total difficulty\r\nactual td: %d\r\nexpected td: %d", payload.TotalDifficulty.Int64(), mockTotalDifficulty.Int64()) } } diff --git a/statediff/testhelpers/mocks/blockchain.go b/statediff/testhelpers/mocks/blockchain.go index b5eb6ff9241f..68fc92cc263d 100644 --- a/statediff/testhelpers/mocks/blockchain.go +++ b/statediff/testhelpers/mocks/blockchain.go @@ -18,7 +18,7 @@ package mocks import ( "errors" - + "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -35,6 +35,7 @@ type BlockChain struct { callCount int ChainEvents []core.ChainEvent Receipts map[common.Hash]types.Receipts + TDByHash map[common.Hash]*big.Int } // AddToStateDiffProcessedCollection mock method @@ -89,7 +90,7 @@ func (blockChain *BlockChain) SubscribeChainEvent(ch chan<- core.ChainEvent) eve return subscription } -// SetReceiptsForHash mock method +// SetReceiptsForHash test method func (blockChain *BlockChain) SetReceiptsForHash(hash common.Hash, receipts types.Receipts) { if blockChain.Receipts == nil { blockChain.Receipts = make(map[common.Hash]types.Receipts) @@ -102,7 +103,7 @@ func (blockChain *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts return blockChain.Receipts[hash] } -// SetBlockForNumber mock method +// SetBlockForNumber test method func (blockChain *BlockChain) SetBlockForNumber(block *types.Block, number uint64) { if blockChain.blocksToReturnByNumber == nil { blockChain.blocksToReturnByNumber = make(map[uint64]*types.Block) @@ -114,3 +115,15 @@ func (blockChain *BlockChain) SetBlockForNumber(block *types.Block, number uint6 func (blockChain *BlockChain) GetBlockByNumber(number uint64) *types.Block { return blockChain.blocksToReturnByNumber[number] } + +// GetTdByHash mock method +func (blockChain *BlockChain) GetTdByHash(hash common.Hash) *big.Int { + return blockChain.TDByHash[hash] +} + +func (blockChain *BlockChain) SetTdByHash(hash common.Hash, td *big.Int) { + if blockChain.TDByHash == nil { + blockChain.TDByHash = make(map[common.Hash]*big.Int) + } + blockChain.TDByHash[hash] = td +} diff --git a/statediff/types.go b/statediff/types.go index 95aef777d435..b527221b64ef 100644 --- a/statediff/types.go +++ b/statediff/types.go @@ -36,9 +36,10 @@ type Subscription struct { // Payload packages the data to send to statediff subscriptions type Payload struct { - BlockRlp []byte `json:"blockRlp"` - ReceiptsRlp []byte `json:"receiptsRlp"` - StateDiffRlp []byte `json:"stateDiff" gencodec:"required"` + BlockRlp []byte `json:"blockRlp"` + TotalDifficulty *big.Int `json:"totalDifficulty"` + ReceiptsRlp []byte `json:"receiptsRlp"` + StateDiffRlp []byte `json:"stateDiff" gencodec:"required"` encoded []byte err error