include total difficulty to the payload

This commit is contained in:
Ian Norden 2020-01-16 16:02:12 -06:00
parent 6e05b78bd0
commit c7bfb7eda3
5 changed files with 127 additions and 77 deletions

View File

@ -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 {

View File

@ -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
}

View File

@ -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{
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"),
})
var burnAccount1, _ = rlp.EncodeToBytes(state.Account{
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{
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())
}
}

View File

@ -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
}

View File

@ -37,6 +37,7 @@ type Subscription struct {
// Payload packages the data to send to statediff subscriptions
type Payload struct {
BlockRlp []byte `json:"blockRlp"`
TotalDifficulty *big.Int `json:"totalDifficulty"`
ReceiptsRlp []byte `json:"receiptsRlp"`
StateDiffRlp []byte `json:"stateDiff" gencodec:"required"`