From 2797642dfe907f216949f436933e67dd2fbf984a Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman Date: Fri, 21 Dec 2018 11:14:36 -0600 Subject: [PATCH] Update service loop and fetching previous block --- statediff/builder/builder_test.go | 1 - statediff/service/service.go | 58 +++++++-------- statediff/service/service_test.go | 116 ++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 statediff/service/service_test.go diff --git a/statediff/builder/builder_test.go b/statediff/builder/builder_test.go index 614681ed2..2ba6ca9b8 100644 --- a/statediff/builder/builder_test.go +++ b/statediff/builder/builder_test.go @@ -61,7 +61,6 @@ func TestBuilder(t *testing.T) { blockHash common.Hash } - var ( balanceChange10000 = int64(10000) balanceChange1000 = int64(1000) diff --git a/statediff/service/service.go b/statediff/service/service.go index c308c83b9..3ceebc15b 100644 --- a/statediff/service/service.go +++ b/statediff/service/service.go @@ -3,20 +3,27 @@ package service import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/statediff" b "github.com/ethereum/go-ethereum/statediff/builder" e "github.com/ethereum/go-ethereum/statediff/extractor" p "github.com/ethereum/go-ethereum/statediff/publisher" - "log" + + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) +type BlockChain interface { + SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription + GetBlockByHash(hash common.Hash) *types.Block +} + type StateDiffService struct { - builder *b.Builder - extractor e.Extractor - blockchain *core.BlockChain + Builder *b.Builder + Extractor e.Extractor + BlockChain BlockChain } func NewStateDiffService(db ethdb.Database, blockChain *core.BlockChain) (*StateDiffService, error) { @@ -29,46 +36,35 @@ func NewStateDiffService(db ethdb.Database, blockChain *core.BlockChain) (*State extractor, _ := e.NewExtractor(builder, publisher) return &StateDiffService{ - blockchain: blockChain, - extractor: extractor, + BlockChain: blockChain, + Extractor: extractor, }, nil } func (StateDiffService) Protocols() []p2p.Protocol { return []p2p.Protocol{} - } func (StateDiffService) APIs() []rpc.API { return []rpc.API{} } -func (sds *StateDiffService) loop(sub event.Subscription, events chan core.ChainHeadEvent) { - defer sub.Unsubscribe() +func (sds *StateDiffService) Loop(events chan core.ChainEvent) { + for elem := range events { + currentBlock := elem.Block - for { - select { - case ev, ok := <-events: - if !ok { - log.Fatalf("Error getting chain head event from subscription.") - } - log.Println("doing something with an event", ev) - previousBlock := ev.Block - //TODO: figure out the best way to get the previous block - currentBlock := ev.Block - sds.extractor.ExtractStateDiff(*previousBlock, *currentBlock) - } + parentHash := currentBlock.ParentHash() + parentBlock := sds.BlockChain.GetBlockByHash(parentHash) + + sds.Extractor.ExtractStateDiff(*parentBlock, *currentBlock) } - } + func (sds *StateDiffService) Start(server *p2p.Server) error { - events := make(chan core.ChainHeadEvent, 10) - sub := sds.blockchain.SubscribeChainHeadEvent(events) - - go sds.loop(sub, events) - - return nil -} -func (StateDiffService) Stop() error { + events := make(chan core.ChainEvent, 10) + sds.BlockChain.SubscribeChainEvent(events) + go sds.Loop(events) return nil } + +func (StateDiffService) Stop() error { return nil } diff --git a/statediff/service/service_test.go b/statediff/service/service_test.go new file mode 100644 index 000000000..c739492cf --- /dev/null +++ b/statediff/service/service_test.go @@ -0,0 +1,116 @@ +package service_test + +import ( + "testing" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core" + service2 "github.com/ethereum/go-ethereum/statediff/service" + "reflect" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" + "math/big" + "math/rand" +) + +type MockExtractor struct { + ParentBlocks []types.Block + CurrentBlocks []types.Block + extractError error +} + +func (me *MockExtractor) ExtractStateDiff(parent, current types.Block) (string, error) { + me.ParentBlocks = append(me.ParentBlocks, parent) + me.CurrentBlocks = append(me.CurrentBlocks, current) + + return "", me.extractError +} + +func (me *MockExtractor) SetExtractError(err error) { + me.extractError = err +} + +type MockChain struct { + ParentHashesLookedUp []common.Hash + parentBlocksToReturn []*types.Block + callCount int +} + +func (mc *MockChain) SetParentBlockToReturn(blocks []*types.Block) { + mc.parentBlocksToReturn = blocks +} + +func (mc *MockChain) GetBlockByHash(hash common.Hash) *types.Block { + mc.ParentHashesLookedUp = append(mc.ParentHashesLookedUp, hash) + + var parentBlock types.Block + if len(mc.parentBlocksToReturn) > 0 { + parentBlock = *mc.parentBlocksToReturn[mc.callCount] + } + + mc.callCount++ + return &parentBlock +} + +func (MockChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { + panic("implement me") +} + +func TestServiceLoop(t *testing.T) { + testServiceLoop(t) +} + +var ( + eventsChannel = make(chan core.ChainEvent, 10) + + parentHeader1 = types.Header{Number: big.NewInt(rand.Int63())} + parentHeader2 = types.Header{Number: big.NewInt(rand.Int63())} + + parentBlock1 = types.NewBlock(&parentHeader1, nil, nil, nil) + parentBlock2 = types.NewBlock(&parentHeader2, nil, nil, nil) + + parentHash1 = parentBlock1.Hash() + parentHash2 = parentBlock2.Hash() + + header1 = types.Header{ ParentHash: parentHash1 } + header2 = types.Header{ ParentHash: parentHash2 } + + block1 = types.NewBlock(&header1, nil, nil, nil) + block2 = types.NewBlock(&header2, nil, nil, nil) + + event1 = core.ChainEvent{ Block: block1 } + event2 = core.ChainEvent{ Block: block2 } +) + +func testServiceLoop(t *testing.T) { + eventsChannel <- event1 + eventsChannel <- event2 + + extractor := MockExtractor{} + close(eventsChannel) + + blockChain := MockChain{} + service := service2.StateDiffService{ + Builder: nil, + Extractor: &extractor, + BlockChain: &blockChain, + } + + blockChain.SetParentBlockToReturn([]*types.Block{parentBlock1, parentBlock2}) + service.Loop(eventsChannel) + + //parent and current blocks are passed to the extractor + expectedCurrentBlocks := []types.Block{*block1, *block2} + if !reflect.DeepEqual(extractor.CurrentBlocks, expectedCurrentBlocks) { + t.Errorf("Actual does not equal expected.\nactual:%+v\nexpected: %+v", extractor.CurrentBlocks, expectedCurrentBlocks) + } + expectedParentBlocks := []types.Block{*parentBlock1, *parentBlock2} + if !reflect.DeepEqual(extractor.ParentBlocks, expectedParentBlocks) { + t.Errorf("Actual does not equal expected.\nactual:%+v\nexpected: %+v", extractor.CurrentBlocks, expectedParentBlocks) + } + + //look up the parent block from its hash + expectedHashes := []common.Hash{block1.ParentHash(), block2.ParentHash()} + if !reflect.DeepEqual(blockChain.ParentHashesLookedUp, expectedHashes) { + t.Errorf("Actual does not equal expected.\nactual:%+v\nexpected: %+v", blockChain.ParentHashesLookedUp, expectedHashes) + } +}