mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-09 12:31:21 +00:00
56700620b2
* added extension * added api * lint * more lint * better response * added README.md * README Fixed * README updated * fixed lint
227 lines
6.1 KiB
Go
227 lines
6.1 KiB
Go
package apis
|
|
|
|
import (
|
|
"bytes"
|
|
"math/big"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/common"
|
|
"github.com/ledgerwatch/turbo-geth/common/dbutils"
|
|
"github.com/ledgerwatch/turbo-geth/consensus"
|
|
"github.com/ledgerwatch/turbo-geth/core/state"
|
|
"github.com/ledgerwatch/turbo-geth/core/types"
|
|
"github.com/ledgerwatch/turbo-geth/core/types/accounts"
|
|
"github.com/ledgerwatch/turbo-geth/crypto"
|
|
"github.com/ledgerwatch/turbo-geth/ethdb"
|
|
"github.com/ledgerwatch/turbo-geth/ethdb/remote/remotechain"
|
|
"github.com/ledgerwatch/turbo-geth/params"
|
|
"github.com/ledgerwatch/turbo-geth/rpc"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// ChangeSetReader is a mock StateWriter that accumulates changes in-memory into ChangeSets.
|
|
type RemoteReader struct {
|
|
accountReads map[common.Address]bool
|
|
storageReads map[common.Hash]bool
|
|
blockNr uint64
|
|
db ethdb.KV
|
|
}
|
|
|
|
type RemoteContext struct {
|
|
db ethdb.KV
|
|
}
|
|
|
|
type powEngine struct {
|
|
}
|
|
|
|
func (c *powEngine) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
|
|
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) Finalize(chainConfig *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []*types.Transaction, uncles []*types.Header) {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) FinalizeAndAssemble(chainConfig *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []*types.Transaction,
|
|
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) Seal(_ consensus.Cancel, chain consensus.ChainReader, block *types.Block, results chan<- consensus.ResultWithContext, stop <-chan struct{}) error {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) SealHash(header *types.Header) common.Hash {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
|
|
panic("must not be called")
|
|
}
|
|
func (c *powEngine) APIs(chain consensus.ChainReader) []rpc.API {
|
|
panic("must not be called")
|
|
}
|
|
|
|
func (c *powEngine) Close() error {
|
|
panic("must not be called")
|
|
}
|
|
|
|
func (c *powEngine) Author(header *types.Header) (common.Address, error) {
|
|
return header.Coinbase, nil
|
|
}
|
|
|
|
func NewRemoteReader(db ethdb.KV, blockNr uint64) *RemoteReader {
|
|
return &RemoteReader{
|
|
accountReads: make(map[common.Address]bool),
|
|
storageReads: make(map[common.Hash]bool),
|
|
db: db,
|
|
blockNr: blockNr,
|
|
}
|
|
}
|
|
|
|
func (r *RemoteReader) GetAccountReads() [][]byte {
|
|
output := make([][]byte, 0)
|
|
for key := range r.accountReads {
|
|
output = append(output, key.Bytes())
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (r *RemoteReader) GetStorageReads() [][]byte {
|
|
output := make([][]byte, 0)
|
|
for key := range r.storageReads {
|
|
output = append(output, key.Bytes())
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (r *RemoteReader) ReadAccountData(address common.Address) (*accounts.Account, error) {
|
|
r.accountReads[address] = true
|
|
addrHash, _ := common.HashData(address[:])
|
|
key := addrHash[:]
|
|
r.accountReads[address] = true
|
|
composite, _ := dbutils.CompositeKeySuffix(key, r.blockNr)
|
|
var dat []byte
|
|
err := r.db.View(context.Background(), func(tx ethdb.Tx) error {
|
|
{
|
|
hB := tx.Bucket(dbutils.AccountsHistoryBucket)
|
|
hC := hB.Cursor()
|
|
hK, hV, err := hC.Seek(composite)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if hK != nil && bytes.HasPrefix(hK, key) {
|
|
dat = make([]byte, len(hV))
|
|
copy(dat, hV)
|
|
return nil
|
|
}
|
|
}
|
|
{
|
|
b := tx.Bucket(dbutils.AccountsBucket)
|
|
c := b.Cursor()
|
|
k, v, err := c.Seek(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if k != nil && bytes.Equal(k, key) {
|
|
dat = make([]byte, len(v))
|
|
copy(dat, v)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return ethdb.ErrKeyNotFound
|
|
})
|
|
if err != nil || dat == nil || len(dat) == 0 {
|
|
return nil, nil
|
|
}
|
|
acc := accounts.NewAccount()
|
|
err = acc.DecodeForStorage(dat)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &acc, nil
|
|
}
|
|
|
|
func (r *RemoteReader) ReadAccountStorage(address common.Address, incarnation uint64, key *common.Hash) ([]byte, error) {
|
|
keyHash, _ := common.HashData(key[:])
|
|
addrHash, _ := common.HashData(address[:])
|
|
|
|
compositeKey := dbutils.GenerateCompositeStorageKey(addrHash, incarnation, keyHash)
|
|
var val []byte
|
|
err := r.db.View(context.Background(), func(tx ethdb.Tx) error {
|
|
b := tx.Bucket(dbutils.StorageBucket)
|
|
v, err := b.Get(compositeKey)
|
|
val = v
|
|
return err
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.storageReads[*key] = true
|
|
return val, nil
|
|
}
|
|
|
|
func (r *RemoteReader) ReadAccountCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
|
if bytes.Equal(codeHash[:], crypto.Keccak256(nil)) {
|
|
return nil, nil
|
|
}
|
|
var val []byte
|
|
err := r.db.View(context.Background(), func(tx ethdb.Tx) error {
|
|
b := tx.Bucket(dbutils.StorageBucket)
|
|
v, err := b.Get(codeHash[:])
|
|
val = v
|
|
return err
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return val, nil
|
|
}
|
|
|
|
func (r *RemoteReader) ReadAccountCodeSize(address common.Address, codeHash common.Hash) (int, error) {
|
|
if bytes.Equal(codeHash[:], crypto.Keccak256(nil)) {
|
|
return 0, nil
|
|
}
|
|
var val []byte
|
|
err := r.db.View(context.Background(), func(tx ethdb.Tx) error {
|
|
b := tx.Bucket(dbutils.StorageBucket)
|
|
v, err := b.Get(codeHash[:])
|
|
val = v
|
|
return err
|
|
})
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return len(val), nil
|
|
}
|
|
|
|
func NewRemoteContext(db ethdb.KV) *RemoteContext {
|
|
return &RemoteContext{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
func (e *RemoteContext) Engine() consensus.Engine {
|
|
return &powEngine{}
|
|
}
|
|
|
|
func (e *RemoteContext) GetHeader(hash common.Hash, number uint64) *types.Header {
|
|
var header *types.Header
|
|
_ = e.db.View(context.Background(), func(tx ethdb.Tx) error {
|
|
h, _ := remotechain.ReadHeader(tx, hash, number)
|
|
header = h
|
|
return nil
|
|
})
|
|
return header
|
|
}
|