store code updates

This commit is contained in:
Roy Crihfield 2023-06-21 01:19:58 +08:00
parent ddf9aff945
commit 0fabb5a35d
2 changed files with 50 additions and 45 deletions

View File

@ -21,7 +21,6 @@ import (
) )
type BlockChain interface { type BlockChain interface {
// SubscribeChainEvent(ch chan<- plugeth.ChainEvent) plugeth.Subscription
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
CurrentBlock() *types.Header CurrentBlock() *types.Header
GetBlockByHash(hash common.Hash) *types.Block GetBlockByHash(hash common.Hash) *types.Block
@ -33,26 +32,30 @@ type BlockChain interface {
StateCache() adapt.StateView StateCache() adapt.StateView
} }
// Adapts the plugeth Backend to the blockChain interface // CodeStore stores contract code hashes to data in a synchronized map
type backendBlockChain struct { type CodeStore struct {
restricted.Backend code map[plugeth.Hash][]byte
ctx context.Context
// code mappings exposed in StateCache, safe for concurrent access
code map[common.Hash][]byte
codeMtx sync.RWMutex codeMtx sync.RWMutex
} }
var _ BlockChain = (*backendBlockChain)(nil) // pluginBlockChain adapts the plugeth Backend to the blockChain interface
type pluginBlockChain struct {
restricted.Backend
ctx context.Context
code *CodeStore
}
func NewPluginBlockChain(backend restricted.Backend) BlockChain { var _ BlockChain = (*pluginBlockChain)(nil)
return &backendBlockChain{
func NewPluginBlockChain(backend restricted.Backend, code *CodeStore) BlockChain {
return &pluginBlockChain{
Backend: backend, Backend: backend,
ctx: context.Background(), ctx: context.Background(),
code: code,
} }
} }
func (b backendBlockChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { func (b *pluginBlockChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
bufferChan := make(chan plugeth.ChainEvent, chainEventChanSize) bufferChan := make(chan plugeth.ChainEvent, chainEventChanSize)
sub := b.Backend.SubscribeChainEvent(bufferChan) sub := b.Backend.SubscribeChainEvent(bufferChan)
go func() { go func() {
@ -69,12 +72,12 @@ func (b backendBlockChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.
return sub return sub
} }
func (b *backendBlockChain) CurrentBlock() *types.Header { func (b *pluginBlockChain) CurrentBlock() *types.Header {
buf := b.Backend.CurrentBlock() buf := b.Backend.CurrentBlock()
return utils.MustDecode[types.Header](buf) return utils.MustDecode[types.Header](buf)
} }
func (b *backendBlockChain) GetBlockByHash(hash common.Hash) *types.Block { func (b *pluginBlockChain) GetBlockByHash(hash common.Hash) *types.Block {
buf, err := b.Backend.BlockByHash(b.ctx, plugeth.Hash(hash)) buf, err := b.Backend.BlockByHash(b.ctx, plugeth.Hash(hash))
if err != nil { if err != nil {
panic(err) panic(err)
@ -82,7 +85,7 @@ func (b *backendBlockChain) GetBlockByHash(hash common.Hash) *types.Block {
return utils.MustDecode[types.Block](buf) return utils.MustDecode[types.Block](buf)
} }
func (b *backendBlockChain) GetBlockByNumber(number uint64) *types.Block { func (b *pluginBlockChain) GetBlockByNumber(number uint64) *types.Block {
buf, err := b.Backend.BlockByNumber(b.ctx, int64(number)) buf, err := b.Backend.BlockByNumber(b.ctx, int64(number))
if err != nil { if err != nil {
panic(err) panic(err)
@ -90,7 +93,7 @@ func (b *backendBlockChain) GetBlockByNumber(number uint64) *types.Block {
return utils.MustDecode[types.Block](buf) return utils.MustDecode[types.Block](buf)
} }
func (b *backendBlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { func (b *pluginBlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
buf, err := b.Backend.GetReceipts(b.ctx, plugeth.Hash(hash)) buf, err := b.Backend.GetReceipts(b.ctx, plugeth.Hash(hash))
if err != nil { if err != nil {
panic(err) panic(err)
@ -103,37 +106,21 @@ func (b *backendBlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
return receipts return receipts
} }
func (b *backendBlockChain) GetTd(hash common.Hash, number uint64) *big.Int { func (b *pluginBlockChain) GetTd(hash common.Hash, number uint64) *big.Int {
return b.Backend.GetTd(b.ctx, plugeth.Hash(hash)) return b.Backend.GetTd(b.ctx, plugeth.Hash(hash))
} }
func (b *backendBlockChain) StateCache() adapt.StateView { func (b *pluginBlockChain) StateCache() adapt.StateView {
return &pluginStateView{backend: b} return &pluginStateView{backend: b}
} }
func (b *backendBlockChain) ChainConfig() *params.ChainConfig { func (b *pluginBlockChain) ChainConfig() *params.ChainConfig {
return adapt.ChainConfig(b.Backend.ChainConfig()) return adapt.ChainConfig(b.Backend.ChainConfig())
} }
func (b *backendBlockChain) getCode(hash common.Hash) ([]byte, error) {
b.codeMtx.RLock()
defer b.codeMtx.RUnlock()
code, has := b.code[hash]
if !has {
return nil, errors.New("code not found")
}
return copybytes(code), nil
}
func (b *backendBlockChain) setCode(hash common.Hash, code []byte) {
b.codeMtx.Lock()
defer b.codeMtx.Unlock()
b.code[hash] = code
}
// exposes a StateView from a combination of plugeth's core Backend and cached contract code // exposes a StateView from a combination of plugeth's core Backend and cached contract code
type pluginStateView struct { type pluginStateView struct {
backend *backendBlockChain backend *pluginBlockChain
} }
func (p *pluginStateView) OpenTrie(root common.Hash) (adapt.StateTrie, error) { func (p *pluginStateView) OpenTrie(root common.Hash) (adapt.StateTrie, error) {
@ -145,7 +132,21 @@ func (p *pluginStateView) OpenTrie(root common.Hash) (adapt.StateTrie, error) {
} }
func (p *pluginStateView) ContractCode(hash common.Hash) ([]byte, error) { func (p *pluginStateView) ContractCode(hash common.Hash) ([]byte, error) {
return p.backend.getCode(hash) return p.backend.code.Get(plugeth.Hash(hash))
} }
func copybytes(b []byte) []byte { return []byte(string(b)) } func (b *CodeStore) Get(hash plugeth.Hash) ([]byte, error) {
b.codeMtx.RLock()
defer b.codeMtx.RUnlock()
code, has := b.code[hash]
if !has {
return nil, errors.New("code not found")
}
return []byte(string(code)), nil
}
func (b *CodeStore) Set(hash plugeth.Hash, code []byte) {
b.codeMtx.Lock()
defer b.codeMtx.Unlock()
b.code[hash] = code
}

View File

@ -20,6 +20,7 @@ var (
gethContext core.Context gethContext core.Context
service *statediff.Service service *statediff.Service
blockchain statediff.BlockChain blockchain statediff.BlockChain
codeStore statediff.CodeStore
) )
func Initialize(ctx core.Context, pl core.PluginLoader, logger core.Logger) { func Initialize(ctx core.Context, pl core.PluginLoader, logger core.Logger) {
@ -47,12 +48,12 @@ func InitializeNode(stack core.Node, b core.Backend) {
return return
} }
serviceConfig := GetConfig() serviceConfig := GetConfig()
chain := statediff.NewPluginBlockChain(backend) blockchain = statediff.NewPluginBlockChain(backend, &codeStore)
var indexer interfaces.StateDiffIndexer var indexer interfaces.StateDiffIndexer
if serviceConfig.IndexerConfig != nil { if serviceConfig.IndexerConfig != nil {
info := node.Info{ info := node.Info{
GenesisBlock: chain.GetBlockByNumber(0).Hash().String(), GenesisBlock: blockchain.GetBlockByNumber(0).Hash().String(),
NetworkID: strconv.FormatUint(networkid, 10), NetworkID: strconv.FormatUint(networkid, 10),
ChainID: backend.ChainConfig().ChainID.Uint64(), ChainID: backend.ChainConfig().ChainID.Uint64(),
ID: serviceConfig.ID, ID: serviceConfig.ID,
@ -65,7 +66,7 @@ func InitializeNode(stack core.Node, b core.Backend) {
log.Error("failed to construct indexer", "error", err) log.Error("failed to construct indexer", "error", err)
} }
} }
service, err := statediff.NewService(serviceConfig, chain, backend, indexer) service, err := statediff.NewService(serviceConfig, blockchain, backend, indexer)
if err != nil { if err != nil {
log.Error("failed to construct service", "error", err) log.Error("failed to construct service", "error", err)
} }
@ -88,16 +89,19 @@ func GetAPIs(stack core.Node, backend core.Backend) []core.API {
// StateUpdate gives us updates about state changes made in each block. // StateUpdate gives us updates about state changes made in each block.
// We extract contract code here, since it's not exposed by plugeth's state interfaces. // We extract contract code here, since it's not exposed by plugeth's state interfaces.
func StateUpdate(blockRoot core.Hash, func StateUpdate(
blockRoot core.Hash,
parentRoot core.Hash, parentRoot core.Hash,
destructs map[core.Hash]struct{}, destructs map[core.Hash]struct{},
accounts map[core.Hash][]byte, accounts map[core.Hash][]byte,
storage map[core.Hash]map[core.Hash][]byte, storage map[core.Hash]map[core.Hash][]byte,
codeUpdates map[core.Hash][]byte) { codeUpdates map[core.Hash][]byte) {
if service == nil { if blockchain == nil {
log.Error("StateUpdate called before InitializeNode", "root", blockRoot) log.Warn("StateUpdate called before InitializeNode", "root", blockRoot)
return return
} }
// blockchain. for hash, code := range codeUpdates {
codeStore.Set(hash, code)
}
} }