store code updates
This commit is contained in:
parent
ddf9aff945
commit
0fabb5a35d
@ -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
|
||||||
|
}
|
||||||
|
18
main/main.go
18
main/main.go
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user