8000 Added the EVM as a plugin by StephenButtolph · Pull Request #2 · ava-labs/coreth · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Added the EVM as a plugin #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
619 changes: 619 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions plugin/evm/block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// (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()) }
66 changes: 66 additions & 0 deletions plugin/evm/database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// (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) }
19 changes: 19 additions & 0 deletions plugin/evm/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// (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{} }
122 changes: 122 additions & 0 deletions plugin/evm/service.go
2E87
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// (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 * F438 DebugAPI) IssueBlock(ctx context.Context) error {
api.vm.ctx.Log.Info("Issuing a new block")

return api.vm.tryBlockGen()
}
22 changes: 22 additions & 0 deletions plugin/evm/static_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// (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
}
64 changes: 64 additions & 0 deletions plugin/evm/static_service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// (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)
}
}
Loading
0