Write state diff to CSV #2
@ -61,7 +61,6 @@ func TestBuilder(t *testing.T) {
|
|||||||
blockHash common.Hash
|
blockHash common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
balanceChange10000 = int64(10000)
|
balanceChange10000 = int64(10000)
|
||||||
balanceChange1000 = int64(1000)
|
balanceChange1000 = int64(1000)
|
||||||
|
@ -3,20 +3,27 @@ package service
|
|||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/statediff"
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
b "github.com/ethereum/go-ethereum/statediff/builder"
|
b "github.com/ethereum/go-ethereum/statediff/builder"
|
||||||
e "github.com/ethereum/go-ethereum/statediff/extractor"
|
e "github.com/ethereum/go-ethereum/statediff/extractor"
|
||||||
p "github.com/ethereum/go-ethereum/statediff/publisher"
|
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 {
|
type StateDiffService struct {
|
||||||
builder *b.Builder
|
Builder *b.Builder
|
||||||
extractor e.Extractor
|
Extractor e.Extractor
|
||||||
blockchain *core.BlockChain
|
BlockChain BlockChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateDiffService(db ethdb.Database, blockChain *core.BlockChain) (*StateDiffService, error) {
|
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)
|
extractor, _ := e.NewExtractor(builder, publisher)
|
||||||
return &StateDiffService{
|
return &StateDiffService{
|
||||||
blockchain: blockChain,
|
BlockChain: blockChain,
|
||||||
extractor: extractor,
|
Extractor: extractor,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (StateDiffService) Protocols() []p2p.Protocol {
|
func (StateDiffService) Protocols() []p2p.Protocol {
|
||||||
return []p2p.Protocol{}
|
return []p2p.Protocol{}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (StateDiffService) APIs() []rpc.API {
|
func (StateDiffService) APIs() []rpc.API {
|
||||||
return []rpc.API{}
|
return []rpc.API{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sds *StateDiffService) loop(sub event.Subscription, events chan core.ChainHeadEvent) {
|
func (sds *StateDiffService) Loop(events chan core.ChainEvent) {
|
||||||
defer sub.Unsubscribe()
|
for elem := range events {
|
||||||
|
currentBlock := elem.Block
|
||||||
|
|
||||||
for {
|
parentHash := currentBlock.ParentHash()
|
||||||
select {
|
parentBlock := sds.BlockChain.GetBlockByHash(parentHash)
|
||||||
case ev, ok := <-events:
|
|
||||||
if !ok {
|
sds.Extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sds *StateDiffService) Start(server *p2p.Server) error {
|
func (sds *StateDiffService) Start(server *p2p.Server) error {
|
||||||
events := make(chan core.ChainHeadEvent, 10)
|
events := make(chan core.ChainEvent, 10)
|
||||||
sub := sds.blockchain.SubscribeChainHeadEvent(events)
|
sds.BlockChain.SubscribeChainEvent(events)
|
||||||
|
go sds.Loop(events)
|
||||||
go sds.loop(sub, events)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (StateDiffService) Stop() error {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (StateDiffService) Stop() error { return nil }
|
||||||
|
116
statediff/service/service_test.go
Normal file
116
statediff/service/service_test.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user