aboutsummaryrefslogtreecommitdiff
path: root/plugin/evm
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/evm')
-rw-r--r--plugin/evm/block.go75
-rw-r--r--plugin/evm/database.go66
-rw-r--r--plugin/evm/factory.go19
-rw-r--r--plugin/evm/service.go122
-rw-r--r--plugin/evm/static_service.go22
-rw-r--r--plugin/evm/static_service_test.go64
-rw-r--r--plugin/evm/vm.go502
-rw-r--r--plugin/evm/vm_genesis_parse_test.go32
8 files changed, 0 insertions, 902 deletions
diff --git a/plugin/evm/block.go b/plugin/evm/block.go
deleted file mode 100644
index ec47490..0000000
--- a/plugin/evm/block.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "fmt"
-
- "github.com/ava-labs/go-ethereum/core/types"
- "github.com/ava-labs/go-ethereum/rlp"
-
- "github.com/ava-labs/gecko/ids"
- "github.com/ava-labs/gecko/snow/choices"
- "github.com/ava-labs/gecko/snow/consensus/snowman"
-)
-
-// Block implements the snowman.Block interface
-type Block struct {
- id ids.ID
- ethBlock *types.Block
- vm *VM
-}
-
-// ID implements the snowman.Block interface
-func (b *Block) ID() ids.ID { return b.id }
-
-// Accept implements the snowman.Block interface
-func (b *Block) Accept() {
- b.vm.ctx.Log.Verbo("Block %s is accepted", b.ID())
- b.vm.updateStatus(b.ID(), choices.Accepted)
-}
-
-// Reject implements the snowman.Block interface
-func (b *Block) Reject() {
- b.vm.ctx.Log.Verbo("Block %s is rejected", b.ID())
- b.vm.updateStatus(b.ID(), choices.Rejected)
-}
-
-// Status implements the snowman.Block interface
-func (b *Block) Status() choices.Status {
- status := b.vm.getCachedStatus(b.ID())
- if status == choices.Unknown && b.ethBlock != nil {
- return choices.Processing
- }
- return status
-}
-
-// Parent implements the snowman.Block interface
-func (b *Block) Parent() snowman.Block {
- parentID := ids.NewID(b.ethBlock.ParentHash())
- block := &Block{
- id: parentID,
- ethBlock: b.vm.getCachedBlock(parentID),
- vm: b.vm,
- }
- b.vm.ctx.Log.Verbo("Parent(%s) has status: %s", block.ID(), block.Status())
- return block
-}
-
-// Verify implements the snowman.Block interface
-func (b *Block) Verify() error {
- _, err := b.vm.chain.InsertChain([]*types.Block{b.ethBlock})
- return err
-}
-
-// Bytes implements the snowman.Block interface
-func (b *Block) Bytes() []byte {
- res, err := rlp.EncodeToBytes(b.ethBlock)
- if err != nil {
- panic(err)
- }
- return res
-}
-
-func (b *Block) String() string { return fmt.Sprintf("EVM block, ID = %s", b.ID()) }
diff --git a/plugin/evm/database.go b/plugin/evm/database.go
deleted file mode 100644
index de592e1..0000000
--- a/plugin/evm/database.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "errors"
-
- "github.com/ava-labs/go-ethereum/ethdb"
-
- "github.com/ava-labs/gecko/database"
-)
-
-var (
- errOpNotSupported = errors.New("this operation is not supported")
-)
-
-// Database implements ethdb.Database
-type Database struct{ database.Database }
-
-// HasAncient returns an error as we don't have a backing chain freezer.
-func (db Database) HasAncient(kind string, number uint64) (bool, error) {
- return false, errOpNotSupported
-}
-
-// Ancient returns an error as we don't have a backing chain freezer.
-func (db Database) Ancient(kind string, number uint64) ([]byte, error) { return nil, errOpNotSupported }
-
-// Ancients returns an error as we don't have a backing chain freezer.
-func (db Database) Ancients() (uint64, error) { return 0, errOpNotSupported }
-
-// AncientSize returns an error as we don't have a backing chain freezer.
-func (db Database) AncientSize(kind string) (uint64, error) { return 0, errOpNotSupported }
-
-// AppendAncient returns an error as we don't have a backing chain freezer.
-func (db Database) AppendAncient(number uint64, hash, header, body, receipts, td []byte) error {
- return errOpNotSupported
-}
-
-// TruncateAncients returns an error as we don't have a backing chain freezer.
-func (db Database) TruncateAncients(items uint64) error { return errOpNotSupported }
-
-// Sync returns an error as we don't have a backing chain freezer.
-func (db Database) Sync() error { return errOpNotSupported }
-
-// NewBatch implements ethdb.Database
-func (db Database) NewBatch() ethdb.Batch { return Batch{db.Database.NewBatch()} }
-
-// NewIterator implements ethdb.Database
-func (db Database) NewIterator() ethdb.Iterator { return db.Database.NewIterator() }
-
-// NewIteratorWithPrefix implements ethdb.Database
-func (db Database) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator {
- return db.NewIteratorWithPrefix(prefix)
-}
-
-// NewIteratorWithStart implements ethdb.Database
-func (db Database) NewIteratorWithStart(start []byte) ethdb.Iterator {
- return db.NewIteratorWithStart(start)
-}
-
-// Batch implements ethdb.Batch
-type Batch struct{ database.Batch }
-
-// Replay implements ethdb.Batch
-func (batch Batch) Replay(w ethdb.KeyValueWriter) error { return batch.Batch.Replay(w) }
diff --git a/plugin/evm/factory.go b/plugin/evm/factory.go
deleted file mode 100644
index a4c0eca..0000000
--- a/plugin/evm/factory.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "github.com/ava-labs/gecko/ids"
-)
-
-// ID this VM should be referenced by
-var (
- ID = ids.NewID([32]byte{'e', 'v', 'm'})
-)
-
-// Factory ...
-type Factory struct{}
-
-// New ...
-func (f *Factory) New() interface{} { return &VM{} }
diff --git a/plugin/evm/service.go b/plugin/evm/service.go
deleted file mode 100644
index 70135cc..0000000
--- a/plugin/evm/service.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "context"
- "crypto/rand"
- "fmt"
- "math/big"
-
- "github.com/ava-labs/coreth"
-
- "github.com/ava-labs/go-ethereum/common"
- "github.com/ava-labs/go-ethereum/common/hexutil"
- "github.com/ava-labs/go-ethereum/core/types"
- "github.com/ava-labs/go-ethereum/crypto"
-)
-
-const (
- version = "Athereum 1.0"
-)
-
-// test constants
-const (
- GenesisTestAddr = "0x751a0b96e1042bee789452ecb20253fba40dbe85"
- GenesisTestKey = "0xabd71b35d559563fea757f0f5edbde286fb8c043105b15abb7cd57189306d7d1"
-)
-
-// DebugAPI introduces helper functions for debuging
-type DebugAPI struct{ vm *VM }
-
-// SnowmanAPI introduces snowman specific functionality to the evm
-type SnowmanAPI struct{ vm *VM }
-
-// NetAPI offers network related API methods
-type NetAPI struct{ vm *VM }
-
-// NewNetAPI creates a new net API instance.
-func NewNetAPI(vm *VM) *NetAPI { return &NetAPI{vm} }
-
-// Listening returns an indication if the node is listening for network connections.
-func (s *NetAPI) Listening() bool { return true } // always listening
-
-// PeerCount returns the number of connected peers
-func (s *NetAPI) PeerCount() hexutil.Uint { return hexutil.Uint(0) } // TODO: report number of connected peers
-
-// Version returns the current ethereum protocol version.
-func (s *NetAPI) Version() string { return fmt.Sprintf("%d", s.vm.networkID) }
-
-// Web3API offers helper API methods
-type Web3API struct{}
-
-// ClientVersion returns the version of the vm running
-func (s *Web3API) ClientVersion() string { return version }
-
-// Sha3 returns the bytes returned by hashing [input] with Keccak256
-func (s *Web3API) Sha3(input hexutil.Bytes) hexutil.Bytes { return crypto.Keccak256(input) }
-
-// GetAcceptedFrontReply defines the reply that will be sent from the
-// GetAcceptedFront API call
-type GetAcceptedFrontReply struct {
- Hash common.Hash `json:"hash"`
- Number *big.Int `json:"number"`
-}
-
-// GetAcceptedFront returns the last accepted block's hash and height
-func (api *SnowmanAPI) GetAcceptedFront(ctx context.Context) (*GetAcceptedFrontReply, error) {
- blk := api.vm.getLastAccepted().ethBlock
- return &GetAcceptedFrontReply{
- Hash: blk.Hash(),
- Number: blk.Number(),
- }, nil
-}
-
-// GetGenesisBalance returns the current funds in the genesis
-func (api *DebugAPI) GetGenesisBalance(ctx context.Context) (*hexutil.Big, error) {
- lastAccepted := api.vm.getLastAccepted()
- api.vm.ctx.Log.Verbo("Currently accepted block front: %s", lastAccepted.ethBlock.Hash().Hex())
- state, err := api.vm.chain.BlockState(lastAccepted.ethBlock)
- if err != nil {
- return nil, err
- }
- return (*hexutil.Big)(state.GetBalance(common.HexToAddress(GenesisTestAddr))), nil
-}
-
-// SpendGenesis funds
-func (api *DebugAPI) SpendGenesis(ctx context.Context, nonce uint64) error {
- api.vm.ctx.Log.Info("Spending the genesis")
-
- value := big.NewInt(1000000000000)
- gasLimit := 21000
- gasPrice := big.NewInt(1000000000)
-
- genPrivateKey, err := crypto.HexToECDSA(GenesisTestKey[2:])
- if err != nil {
- return err
- }
- bob, err := coreth.NewKey(rand.Reader)
- if err != nil {
- return err
- }
-
- tx := types.NewTransaction(nonce, bob.Address, value, uint64(gasLimit), gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.NewEIP155Signer(api.vm.chainID), genPrivateKey)
- if err != nil {
- return err
- }
-
- if err := api.vm.issueRemoteTxs([]*types.Transaction{signedTx}); err != nil {
- return err
- }
-
- return nil
-}
-
-// IssueBlock to the chain
-func (api *DebugAPI) IssueBlock(ctx context.Context) error {
- api.vm.ctx.Log.Info("Issuing a new block")
-
- return api.vm.tryBlockGen()
-}
diff --git a/plugin/evm/static_service.go b/plugin/evm/static_service.go
deleted file mode 100644
index d3870ca..0000000
--- a/plugin/evm/static_service.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "context"
- "encoding/json"
-
- "github.com/ava-labs/coreth/core"
- "github.com/ava-labs/gecko/utils/formatting"
-)
-
-// StaticService defines the static API services exposed by the evm
-type StaticService struct{}
-
-// BuildGenesis returns the UTXOs such that at least one address in [args.Addresses] is
-// referenced in the UTXO.
-func (*StaticService) BuildGenesis(_ context.Context, args *core.Genesis) (formatting.CB58, error) {
- bytes, err := json.Marshal(args)
- return formatting.CB58{Bytes: bytes}, err
-}
diff --git a/plugin/evm/static_service_test.go b/plugin/evm/static_service_test.go
deleted file mode 100644
index c492798..0000000
--- a/plugin/evm/static_service_test.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "math/big"
- "testing"
-
- "github.com/ava-labs/go-ethereum/common"
- "github.com/ava-labs/go-ethereum/params"
-
- "github.com/ava-labs/coreth/core"
-)
-
-func TestBuildGenesis(t *testing.T) {
- expected := "3wP629bGfSGj9trh1UNBp5qGRGCcma5d8ezLeSmd9hnUJjSMUJesHHoxbZNcVUC9CjH7PEGNA96htNTd1saZCMt1Mf1dZFG7JDhcYNok6RS4TZufejXdxbVVgquohSa7nCCcrXpiVeiRFwzLJAxyQbXzYRhaCRtcDDfCcqfaVdtkFsPbNeQ49pDTbEC5hVkmfopeQ2Zz8tAG5QXKBdbYBCukR3xNHJ4xDxeixmEwPr1odb42yQRYrL7xREKNn2LFoFwAWUjBTsCkf5GPNgY2GvvN9o8wFWXTroW5fp754DhpdxHYxkMTfuE9DGyNWHTyrEbrUHutUdsfitcSHVj5ctFtkN2wGCs3cyv1eRRNvFFMggWTbarjne6AYaeCrJ631qAu3CbrUtrTH5N2E6G2yQKX4sT4Sk3qWPJdsGXuT95iKKcgNn1u5QRHHw9DXXuGPpJjkcKQRGUCuqpXy61iF5RNPEwAwKDa8f2Y25WMmNgWynUuLj8iSAyePj7USPWk54QFUr86ApVzqAdzzdD1qSVScpmudGnGbz9UNXdzHqSot6XLrNTYsgkabiu6TGntFm7qywbCRmtNdBuT9aznGQdUVimjt5QzUz68HXhUxBzTkrz7yXfVGV5JcWxVHQXYS4oc41U5yu83mH3A7WBrZLVq6UyNrvQVbim5nDxeKKbALPxwzVwywjgY5cp39AvzGnY8CX2AtuBNnKmZaAvG8JWAkx3yxjnJrwWhLgpDQYcCvRp2jg1EPBqN8FKJxSPE6eedjDHDJfB57mNzyEtmg22BPnem3eLdiovX8awkhBUHdE7uPrapNSVprnS85u1saW2Kwza3FsS2jAM3LckGW8KdtfPTpHBTRKAUo49zZLuPsyGL5WduedGyAdaM3a2KPoyXuz4UbexTVUWFNypFvvgyoDS8FMxDCNoMMaD7y4yVnoDpSpVFEVZD6EuSGHe9U8Ew57xLPbjhepDx6"
-
- balance, success := new(big.Int).SetString("33b2e3c9fd0804000000000", 16)
- if !success {
- t.Fatal("Failed to initialize balance")
- }
-
- args := core.Genesis{
- Config: &params.ChainConfig{
- ChainID: big.NewInt(43110),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: big.NewInt(0),
- DAOForkSupport: true,
- EIP150Block: big.NewInt(0),
- EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- },
- Nonce: 0,
- Timestamp: 0,
- ExtraData: []byte{},
- GasLimit: 100000000,
- Difficulty: big.NewInt(0),
- Mixhash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
- Coinbase: common.HexToAddress("0x0000000000000000000000000000000000000000"),
- Alloc: core.GenesisAlloc{
- common.HexToAddress("751a0b96e1042bee789452ecb20253fba40dbe85"): core.GenesisAccount{
- Balance: balance,
- },
- },
- Number: 0,
- GasUsed: 0,
- ParentHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
- }
-
- ss := StaticService{}
- result, err := ss.BuildGenesis(nil, &args)
- if err != nil {
- t.Fatal(err)
- }
-
- if result.String() != expected {
- t.Fatalf("StaticService.BuildGenesis:\nReturned: %s\nExpected: %s", result, expected)
- }
-}
diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go
deleted file mode 100644
index a9011ea..0000000
--- a/plugin/evm/vm.go
+++ /dev/null
@@ -1,502 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "crypto/rand"
- "encoding/json"
- "errors"
- "fmt"
- "math/big"
- "sync"
- "sync/atomic"
- "time"
-
- "github.com/ava-labs/coreth"
- "github.com/ava-labs/coreth/core"
- "github.com/ava-labs/coreth/eth"
- "github.com/ava-labs/coreth/node"
-
- "github.com/ava-labs/go-ethereum/common"
- "github.com/ava-labs/go-ethereum/core/types"
- "github.com/ava-labs/go-ethereum/rlp"
- "github.com/ava-labs/go-ethereum/rpc"
-
- "github.com/ava-labs/gecko/cache"
- "github.com/ava-labs/gecko/database"
- "github.com/ava-labs/gecko/ids"
- "github.com/ava-labs/gecko/snow"
- "github.com/ava-labs/gecko/snow/choices"
- "github.com/ava-labs/gecko/snow/consensus/snowman"
- "github.com/ava-labs/gecko/utils/timer"
-
- commonEng "github.com/ava-labs/gecko/snow/engine/common"
-)
-
-const (
- lastAcceptedKey = "snowman_lastAccepted"
-)
-
-const (
- minBlockTime = 250 * time.Millisecond
- maxBlockTime = 1000 * time.Millisecond
- batchSize = 250
-)
-
-const (
- bdTimerStateMin = iota
- bdTimerStateMax
- bdTimerStateLong
-)
-
-var (
- errEmptyBlock = errors.New("empty block")
- errCreateBlock = errors.New("couldn't create block")
- errUnknownBlock = errors.New("unknown block")
- errBlockFrequency = errors.New("too frequent block issuance")
- errUnsupportedFXs = errors.New("unsupported feature extensions")
-)
-
-func maxDuration(x, y time.Duration) time.Duration {
- if x > y {
- return x
- }
- return y
-}
-
-// VM implements the snowman.ChainVM interface
-type VM struct {
- ctx *snow.Context
-
- chainID *big.Int
- networkID uint64
- chain *coreth.ETHChain
- chaindb Database
- newBlockChan chan *Block
- networkChan chan<- commonEng.Message
- newTxPoolHeadChan chan core.NewTxPoolHeadEvent
-
- txPoolStabilizedHead common.Hash
- txPoolStabilizedOk chan struct{}
- txPoolStabilizedLock sync.Mutex
-
- metalock sync.Mutex
- blockCache, blockStatusCache cache.LRU
- lastAccepted *Block
- writingMetadata uint32
-
- bdlock sync.Mutex
- blockDelayTimer *timer.Timer
- bdTimerState int8
- bdGenWaitFlag bool
- bdGenFlag bool
-
- genlock sync.Mutex
- txSubmitChan <-chan struct{}
-}
-
-/*
- ******************************************************************************
- ********************************* Snowman API ********************************
- ******************************************************************************
- */
-
-// Initialize implements the snowman.ChainVM interface
-func (vm *VM) Initialize(
- ctx *snow.Context,
- db database.Database,
- b []byte,
- toEngine chan<- commonEng.Message,
- fxs []*commonEng.Fx,
-) error {
- if len(fxs) > 0 {
- return errUnsupportedFXs
- }
-
- vm.ctx = ctx
- vm.chaindb = Database{db}
- g := new(core.Genesis)
- err := json.Unmarshal(b, g)
- if err != nil {
- return err
- }
-
- vm.chainID = g.Config.ChainID
-
- config := eth.DefaultConfig
- config.ManualCanonical = true
- config.Genesis = g
- config.Miner.ManualMining = true
- config.Miner.DisableUncle = true
- if err := config.SetGCMode("archive"); err != nil {
- panic(err)
- }
- nodecfg := node.Config{NoUSB: true}
- chain := coreth.NewETHChain(&config, &nodecfg, nil, vm.chaindb)
- vm.chain = chain
- vm.networkID = config.NetworkId
- chain.SetOnHeaderNew(func(header *types.Header) {
- hid := make([]byte, 32)
- _, err := rand.Read(hid)
- if err != nil {
- panic("cannot generate hid")
- }
- header.Extra = append(header.Extra, hid...)
- })
- chain.SetOnSeal(func(block *types.Block) error {
- if len(block.Transactions()) == 0 {
- // this could happen due to the async logic of geth tx pool
- vm.newBlockChan <- nil
- return errEmptyBlock
- }
- return nil
- })
- chain.SetOnSealFinish(func(block *types.Block) error {
- vm.ctx.Log.Verbo("EVM sealed a block")
-
- blk := &Block{
- id: ids.NewID(block.Hash()),
- ethBlock: block,
- vm: vm,
- }
- vm.newBlockChan <- blk
- vm.updateStatus(ids.NewID(block.Hash()), choices.Processing)
- vm.txPoolStabilizedLock.Lock()
- vm.txPoolStabilizedHead = block.Hash()
- vm.txPoolStabilizedLock.Unlock()
- return nil
- })
- chain.SetOnQueryAcceptedBlock(func() *types.Block {
- return vm.getLastAccepted().ethBlock
- })
- vm.blockCache = cache.LRU{Size: 2048}
- vm.blockStatusCache = cache.LRU{Size: 1024}
- vm.newBlockChan = make(chan *Block)
- vm.networkChan = toEngine
- vm.blockDelayTimer = timer.NewTimer(func() {
- vm.bdlock.Lock()
- switch vm.bdTimerState {
- case bdTimerStateMin:
- vm.bdTimerState = bdTimerStateMax
- vm.blockDelayTimer.SetTimeoutIn(maxDuration(maxBlockTime-minBlockTime, 0))
- case bdTimerStateMax:
- vm.bdTimerState = bdTimerStateLong
- }
- tryAgain := vm.bdGenWaitFlag
- vm.bdlock.Unlock()
- if tryAgain {
- vm.tryBlockGen()
- }
- })
- go ctx.Log.RecoverAndPanic(vm.blockDelayTimer.Dispatch)
-
- vm.bdTimerState = bdTimerStateLong
- vm.bdGenWaitFlag = true
- vm.newTxPoolHeadChan = make(chan core.NewTxPoolHeadEvent, 1)
- vm.txPoolStabilizedOk = make(chan struct{}, 1)
- chain.GetTxPool().SubscribeNewHeadEvent(vm.newTxPoolHeadChan)
- // TODO: shutdown this go routine
- go ctx.Log.RecoverAndPanic(func() {
- for {
- select {
- case h := <-vm.newTxPoolHeadChan:
- vm.txPoolStabilizedLock.Lock()
- if vm.txPoolStabilizedHead == h.Block.Hash() {
- vm.txPoolStabilizedOk <- struct{}{}
- vm.txPoolStabilizedHead = common.Hash{}
- }
- vm.txPoolStabilizedLock.Unlock()
- }
- }
- })
- chain.Start()
-
- var lastAccepted *types.Block
- if b, err := vm.chaindb.Get([]byte(lastAcceptedKey)); err == nil {
- var hash common.Hash
- if err = rlp.DecodeBytes(b, &hash); err == nil {
- if block := chain.GetBlockByHash(hash); block == nil {
- vm.ctx.Log.Debug("lastAccepted block not found in chaindb")
- } else {
- lastAccepted = block
- }
- }
- }
- if lastAccepted == nil {
- vm.ctx.Log.Debug("lastAccepted is unavailable, setting to the genesis block")
- lastAccepted = chain.GetGenesisBlock()
- }
- vm.lastAccepted = &Block{
- id: ids.NewID(lastAccepted.Hash()),
- ethBlock: lastAccepted,
- vm: vm,
- }
- vm.ctx.Log.Info(fmt.Sprintf("lastAccepted = %s", vm.lastAccepted.ethBlock.Hash().Hex()))
-
- // TODO: shutdown this go routine
- go vm.ctx.Log.RecoverAndPanic(func() {
- vm.txSubmitChan = vm.chain.GetTxSubmitCh()
- for {
- select {
- case <-vm.txSubmitChan:
- vm.ctx.Log.Verbo("New tx detected, trying to generate a block")
- vm.tryBlockGen()
- case <-time.After(5 * time.Second):
- vm.tryBlockGen()
- }
- }
- })
-
- return nil
-}
-
-// Shutdown implements the snowman.ChainVM interface
-func (vm *VM) Shutdown() {
- if vm.ctx == nil {
- return
- }
-
- vm.writeBackMetadata()
- vm.chain.Stop()
-}
-
-// BuildBlock implements the snowman.ChainVM interface
-func (vm *VM) BuildBlock() (snowman.Block, error) {
- vm.chain.GenBlock()
- block := <-vm.newBlockChan
- if block == nil {
- return nil, errCreateBlock
- }
- // reset the min block time timer
- vm.bdlock.Lock()
- vm.bdTimerState = bdTimerStateMin
- vm.bdGenWaitFlag = false
- vm.bdGenFlag = false
- vm.blockDelayTimer.SetTimeoutIn(minBlockTime)
- vm.bdlock.Unlock()
-
- vm.ctx.Log.Debug("built block 0x%x", block.ID().Bytes())
- // make sure Tx Pool is updated
- <-vm.txPoolStabilizedOk
- return block, nil
-}
-
-// ParseBlock implements the snowman.ChainVM interface
-func (vm *VM) ParseBlock(b []byte) (snowman.Block, error) {
- vm.metalock.Lock()
- defer vm.metalock.Unlock()
-
- ethBlock := new(types.Block)
- if err := rlp.DecodeBytes(b, ethBlock); err != nil {
- return nil, err
- }
- block := &Block{
- id: ids.NewID(ethBlock.Hash()),
- ethBlock: ethBlock,
- vm: vm,
- }
- vm.blockCache.Put(block.ID(), block)
- return block, nil
-}
-
-// GetBlock implements the snowman.ChainVM interface
-func (vm *VM) GetBlock(id ids.ID) (snowman.Block, error) {
- vm.metalock.Lock()
- defer vm.metalock.Unlock()
-
- block := vm.getBlock(id)
- if block == nil {
- return nil, errUnknownBlock
- }
- return block, nil
-}
-
-// SetPreference sets what the current tail of the chain is
-func (vm *VM) SetPreference(blkID ids.ID) {
- err := vm.chain.SetTail(blkID.Key())
- vm.ctx.Log.AssertNoError(err)
-}
-
-// LastAccepted returns the ID of the block that was last accepted
-func (vm *VM) LastAccepted() ids.ID {
- vm.metalock.Lock()
- defer vm.metalock.Unlock()
-
- return vm.lastAccepted.ID()
-}
-
-// CreateHandlers makes new http handlers that can handle API calls
-func (vm *VM) CreateHandlers() map[string]*commonEng.HTTPHandler {
- handler := vm.chain.NewRPCHandler()
- vm.chain.AttachEthService(handler, []string{"eth", "personal", "txpool"})
- handler.RegisterName("net", &NetAPI{vm})
- handler.RegisterName("snowman", &SnowmanAPI{vm})
- handler.RegisterName("web3", &Web3API{})
- handler.RegisterName("debug", &DebugAPI{vm})
-
- return map[string]*commonEng.HTTPHandler{
- "/rpc": &commonEng.HTTPHandler{LockOptions: commonEng.NoLock, Handler: handler},
- "/ws": &commonEng.HTTPHandler{LockOptions: commonEng.NoLock, Handler: handler.WebsocketHandler([]string{"*"})},
- }
-}
-
-// CreateStaticHandlers makes new http handlers that can handle API calls
-func (vm *VM) CreateStaticHandlers() map[string]*commonEng.HTTPHandler {
- handler := rpc.NewServer()
- handler.RegisterName("static", &StaticService{})
- return map[string]*commonEng.HTTPHandler{
- "/rpc": &commonEng.HTTPHandler{LockOptions: commonEng.NoLock, Handler: handler},
- "/ws": &commonEng.HTTPHandler{LockOptions: commonEng.NoLock, Handler: handler.WebsocketHandler([]string{"*"})},
- }
-}
-
-/*
- ******************************************************************************
- *********************************** Helpers **********************************
- ******************************************************************************
- */
-
-func (vm *VM) updateStatus(blockID ids.ID, status choices.Status) {
- vm.metalock.Lock()
- defer vm.metalock.Unlock()
-
- if status == choices.Accepted {
- vm.lastAccepted = vm.getBlock(blockID)
- // TODO: improve this naive implementation
- if atomic.SwapUint32(&vm.writingMetadata, 1) == 0 {
- go vm.ctx.Log.RecoverAndPanic(vm.writeBackMetadata)
- }
- }
- vm.blockStatusCache.Put(blockID, status)
-}
-
-func (vm *VM) getCachedBlock(blockID ids.ID) *types.Block {
- return vm.chain.GetBlockByHash(blockID.Key())
-}
-
-func (vm *VM) tryBlockGen() error {
- vm.bdlock.Lock()
- defer vm.bdlock.Unlock()
- if vm.bdGenFlag {
- // skip if one call already generates a block in this round
- return nil
- }
- vm.bdGenWaitFlag = true
-
- vm.genlock.Lock()
- defer vm.genlock.Unlock()
- // get pending size
- size, err := vm.chain.PendingSize()
- if err != nil {
- return err
- }
- if size == 0 {
- return nil
- }
-
- switch vm.bdTimerState {
- case bdTimerStateMin:
- return nil
- case bdTimerStateMax:
- if size < batchSize {
- return nil
- }
- case bdTimerStateLong:
- // timeout; go ahead and generate a new block anyway
- }
- select {
- case vm.networkChan <- commonEng.PendingTxs:
- // successfully push out the notification; this round ends
- vm.bdGenFlag = true
- default:
- return errBlockFrequency
- }
- return nil
-}
-
-func (vm *VM) getCachedStatus(blockID ids.ID) choices.Status {
- vm.metalock.Lock()
- defer vm.metalock.Unlock()
- status := choices.Processing
-
- if statusIntf, ok := vm.blockStatusCache.Get(blockID); ok {
- status = statusIntf.(choices.Status)
- } else {
- blk := vm.chain.GetBlockByHash(blockID.Key())
- if blk == nil {
- return choices.Unknown
- }
- acceptedBlk := vm.lastAccepted.ethBlock
-
- // TODO: There must be a better way of doing this.
- // Traverse up the chain from the lower block until the indices match
- highBlock := blk
- lowBlock := acceptedBlk
- if highBlock.Number().Cmp(lowBlock.Number()) < 0 {
- highBlock, lowBlock = lowBlock, highBlock
- }
- for highBlock.Number().Cmp(lowBlock.Number()) > 0 {
- highBlock = vm.chain.GetBlockByHash(highBlock.ParentHash())
- }
-
- if highBlock.Hash() == lowBlock.Hash() { // on the same branch
- if blk.Number().Cmp(acceptedBlk.Number()) <= 0 {
- status = choices.Accepted
- }
- } else { // on different branches
- status = choices.Rejected
- }
- }
-
- vm.blockStatusCache.Put(blockID, status)
- return status
-}
-
-func (vm *VM) getBlock(id ids.ID) *Block {
- if blockIntf, ok := vm.blockCache.Get(id); ok {
- return blockIntf.(*Block)
- }
- ethBlock := vm.getCachedBlock(id)
- if ethBlock == nil {
- return nil
- }
- block := &Block{
- id: ids.NewID(ethBlock.Hash()),
- ethBlock: ethBlock,
- vm: vm,
- }
- vm.blockCache.Put(id, block)
- return block
-}
-
-func (vm *VM) issueRemoteTxs(txs []*types.Transaction) error {
- errs := vm.chain.AddRemoteTxs(txs)
- for _, err := range errs {
- if err != nil {
- return err
- }
- }
- return vm.tryBlockGen()
-}
-
-func (vm *VM) writeBackMetadata() {
- vm.metalock.Lock()
- defer vm.metalock.Unlock()
-
- b, err := rlp.EncodeToBytes(vm.lastAccepted.ethBlock.Hash())
- if err != nil {
- vm.ctx.Log.Error("snowman-eth: error while writing back metadata")
- return
- }
- vm.ctx.Log.Debug("writing back metadata")
- vm.chaindb.Put([]byte(lastAcceptedKey), b)
- atomic.StoreUint32(&vm.writingMetadata, 0)
-}
-
-func (vm *VM) getLastAccepted() *Block {
- vm.metalock.Lock()
- defer vm.metalock.Unlock()
-
- return vm.lastAccepted
-}
diff --git a/plugin/evm/vm_genesis_parse_test.go b/plugin/evm/vm_genesis_parse_test.go
deleted file mode 100644
index 9a113fb..0000000
--- a/plugin/evm/vm_genesis_parse_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package evm
-
-import (
- "encoding/json"
- "testing"
-
- "github.com/ava-labs/coreth/core"
-)
-
-func TestParseGenesis(t *testing.T) {
- genesis := []byte(`{"config":{"chainId":43110,"homesteadBlock":0,"daoForkBlock":0,"daoForkSupport":true,"eip150Block":0,"eip150Hash":"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0","eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0},"nonce":"0x0","timestamp":"0x0","extraData":"0x00","gasLimit":"0x5f5e100","difficulty":"0x0","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","alloc":{"751a0b96e1042bee789452ecb20253fba40dbe85":{"balance":"0x33b2e3c9fd0804000000000"}},"number":"0x0","gasUsed":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}`)
-
- genesisBlock := new(core.Genesis)
- err := json.Unmarshal(genesis, genesisBlock)
- if err != nil {
- t.Fatal(err)
- }
-
- marshalledBytes, err := json.Marshal(genesisBlock)
- if err != nil {
- t.Fatal(err)
- }
-
- secondGenesisBlock := new(core.Genesis)
- err = json.Unmarshal(marshalledBytes, secondGenesisBlock)
- if err != nil {
- t.Fatal(err)
- }
-}