-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from ava-labs/revert-4-revert-2-plugin
Added the EVM as a plugin
- Loading branch information
Showing
10 changed files
with
1,542 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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{} } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 *DebugAPI) IssueBlock(ctx context.Context) error { | ||
api.vm.ctx.Log.Info("Issuing a new block") | ||
|
||
return api.vm.tryBlockGen() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: ¶ms.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) | ||
} | ||
} |
Oops, something went wrong.