aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2020-08-19 20:32:18 -0400
committerDeterminant <[email protected]>2020-08-19 20:32:18 -0400
commit1e9599e88a5d88e0090b0ebddfae756e343e605a (patch)
tree92300da4e82db8755ea07f84be61def1079e2840
parentec103c07738b3db70501dee7a7da113edbb68875 (diff)
make the basic X-to-C logic work
-rw-r--r--consensus/clique/clique.go2
-rw-r--r--consensus/dummy/consensus.go11
-rw-r--r--consensus/ethash/consensus.go2
-rw-r--r--core/genesis.go2
-rw-r--r--core/rawdb/accessors_chain.go2
-rw-r--r--core/types/block.go14
-rw-r--r--miner/worker.go1
-rw-r--r--plugin/evm/block.go2
-rw-r--r--plugin/evm/import_tx.go13
-rw-r--r--plugin/evm/service.go16
-rw-r--r--plugin/evm/vm.go46
11 files changed, 64 insertions, 47 deletions
diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go
index d3ad1d9..3714733 100644
--- a/consensus/clique/clique.go
+++ b/consensus/clique/clique.go
@@ -566,7 +566,7 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainReader, header *types.
header.UncleHash = types.CalcUncleHash(nil)
// Assemble and return the final block for sealing
- return types.NewBlock(header, txs, nil, receipts), nil
+ return types.NewBlock(header, txs, nil, receipts, nil), nil
}
// Authorize injects a private key into the consensus engine to mint new blocks
diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go
index 9d8db1e..494e4be 100644
--- a/consensus/dummy/consensus.go
+++ b/consensus/dummy/consensus.go
@@ -19,7 +19,7 @@ import (
)
type OnFinalizeCallbackType = func(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header)
-type OnFinalizeAndAssembleCallbackType = func(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt)
+type OnFinalizeAndAssembleCallbackType = func(state *state.StateDB, txs []*types.Transaction) ([]byte, error)
type OnAPIsCallbackType = func(consensus.ChainReader) []rpc.API
type OnExtraStateChangeType = func(block *types.Block, statedb *state.StateDB) error
@@ -261,14 +261,19 @@ func (self *DummyEngine) Finalize(
func (self *DummyEngine) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
+ var extdata []byte
if self.cb.OnFinalizeAndAssemble != nil {
- self.cb.OnFinalizeAndAssemble(chain, header, state, txs, uncles, receipts)
+ ret, err := self.cb.OnFinalizeAndAssemble(state, txs)
+ extdata = ret
+ if err != nil {
+ return nil, err
+ }
}
// commit the final state root
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
// Header seems complete, assemble into a block and return
- return types.NewBlock(header, txs, uncles, receipts), nil
+ return types.NewBlock(header, txs, uncles, receipts, extdata), nil
}
func (self *DummyEngine) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) (err error) {
diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go
index c325eea..dc88a79 100644
--- a/consensus/ethash/consensus.go
+++ b/consensus/ethash/consensus.go
@@ -576,7 +576,7 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainReader, header *t
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
// Header seems complete, assemble into a block and return
- return types.NewBlock(header, txs, uncles, receipts), nil
+ return types.NewBlock(header, txs, uncles, receipts, nil), nil
}
// SealHash returns the hash of a block prior to it being sealed.
diff --git a/core/genesis.go b/core/genesis.go
index ef490bf..7d21d00 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -294,7 +294,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
statedb.Commit(false)
statedb.Database().TrieDB().Commit(root, true)
- return types.NewBlock(head, nil, nil, nil)
+ return types.NewBlock(head, nil, nil, nil, nil)
}
// Commit writes the block and state of a genesis specification to the database.
diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go
index 7620eac..fdfd6ec 100644
--- a/core/rawdb/accessors_chain.go
+++ b/core/rawdb/accessors_chain.go
@@ -475,7 +475,7 @@ func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
if body == nil {
return nil
}
- return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
+ return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles, body.Version, body.ExtData)
}
// WriteBlock serializes a block into the database, header and body separately.
diff --git a/core/types/block.go b/core/types/block.go
index b3dbcd3..4096d86 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -144,6 +144,8 @@ func rlpHash(x interface{}) (h common.Hash) {
type Body struct {
Transactions []*Transaction
Uncles []*Header
+ Version uint32
+ ExtData []byte `rlp:"nil"`
}
// Block represents an entire block in the Ethereum blockchain.
@@ -212,7 +214,7 @@ type storageblock struct {
// The values of TxHash, UncleHash, ReceiptHash and Bloom in header
// are ignored and set to values derived from the given txs, uncles
// and receipts.
-func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt) *Block {
+func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt, extdata []byte) *Block {
b := &Block{header: CopyHeader(header), td: new(big.Int)}
// TODO: panic if len(txs) != len(receipts)
@@ -241,6 +243,9 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
}
}
+ b.extdata = make([]byte, len(extdata))
+ copy(b.extdata, extdata)
+
return b
}
@@ -387,7 +392,7 @@ func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Ext
func (b *Block) Header() *Header { return CopyHeader(b.header) }
// Body returns the non-header content of the block.
-func (b *Block) Body() *Body { return &Body{b.transactions, b.uncles} }
+func (b *Block) Body() *Body { return &Body{b.transactions, b.uncles, b.version, b.extdata} }
// Size returns the true RLP encoded storage size of the block, either by encoding
// and returning it, or returning a previsouly cached value.
@@ -434,13 +439,16 @@ func (b *Block) WithSeal(header *Header) *Block {
}
// WithBody returns a new block with the given transaction and uncle contents.
-func (b *Block) WithBody(transactions []*Transaction, uncles []*Header) *Block {
+func (b *Block) WithBody(transactions []*Transaction, uncles []*Header, version uint32, extdata []byte) *Block {
block := &Block{
header: CopyHeader(b.header),
transactions: make([]*Transaction, len(transactions)),
uncles: make([]*Header, len(uncles)),
+ extdata: make([]byte, len(extdata)),
+ version: version,
}
copy(block.transactions, transactions)
+ copy(block.extdata, extdata)
for i := range uncles {
block.uncles[i] = CopyHeader(uncles[i])
}
diff --git a/miner/worker.go b/miner/worker.go
index feab0b2..4a6303b 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -751,6 +751,7 @@ func (w *worker) updateSnapshot() {
w.current.txs,
uncles,
w.current.receipts,
+ nil,
)
w.snapshotState = w.current.state.Copy()
diff --git a/plugin/evm/block.go b/plugin/evm/block.go
index a2ffb69..1cbf0b7 100644
--- a/plugin/evm/block.go
+++ b/plugin/evm/block.go
@@ -69,7 +69,7 @@ func (b *Block) Verify() error {
path := []*Block{}
inputs := new(ids.Set)
for {
- if p.Status() == choices.Accepted {
+ if p.Status() == choices.Accepted || p.(*Block).ethBlock.Hash() == vm.genesisHash {
break
}
if ret, hit := vm.blockAtomicInputCache.Get(p.ID()); hit {
diff --git a/plugin/evm/import_tx.go b/plugin/evm/import_tx.go
index ec2ffa4..a61adaa 100644
--- a/plugin/evm/import_tx.go
+++ b/plugin/evm/import_tx.go
@@ -4,21 +4,17 @@
package evm
import (
- //"crypto/ecdsa"
"errors"
"fmt"
"github.com/ava-labs/gecko/database"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow"
- avacrypto "github.com/ava-labs/gecko/utils/crypto"
+ crypto "github.com/ava-labs/gecko/utils/crypto"
"github.com/ava-labs/gecko/utils/math"
"github.com/ava-labs/gecko/vms/components/avax"
- //"github.com/ava-labs/gecko/vms/components/verify"
"github.com/ava-labs/gecko/vms/secp256k1fx"
"github.com/ava-labs/go-ethereum/common"
- "github.com/ava-labs/go-ethereum/log"
- //"github.com/ava-labs/go-ethereum/crypto"
)
var (
@@ -68,7 +64,6 @@ func (tx *UnsignedImportTx) Verify(
case tx.SourceChain.IsZero():
return errWrongChainID
case !tx.SourceChain.Equals(avmID):
- // TODO: remove this check if we allow for P->C swaps
return errWrongChainID
case len(tx.ImportedInputs) == 0:
return errNoImportInputs
@@ -118,7 +113,7 @@ func (tx *UnsignedImportTx) Accept(batch database.Batch) error {
func (vm *VM) newImportTx(
chainID ids.ID, // chain to import from
to common.Address, // Address of recipient
- keys []*avacrypto.PrivateKeySECP256K1R, // Keys to import the funds
+ keys []*crypto.PrivateKeySECP256K1R, // Keys to import the funds
) (*Tx, error) {
if !vm.avm.Equals(chainID) {
return nil, errWrongChainID
@@ -135,7 +130,7 @@ func (vm *VM) newImportTx(
}
importedInputs := []*avax.TransferableInput{}
- signers := [][]*avacrypto.PrivateKeySECP256K1R{}
+ signers := [][]*crypto.PrivateKeySECP256K1R{}
importedAmount := uint64(0)
now := vm.clock.Unix()
@@ -172,6 +167,7 @@ func (vm *VM) newImportTx(
outs := []EVMOutput{}
if importedAmount < vm.txFee { // imported amount goes toward paying tx fee
// TODO: spend EVM balance to compensate vm.txFee-importedAmount
+ return nil, errNoFunds
} else if importedAmount > vm.txFee {
outs = append(outs, EVMOutput{
Address: to,
@@ -192,7 +188,6 @@ func (vm *VM) newImportTx(
}
tx := &Tx{UnsignedTx: utx}
if err := tx.Sign(vm.codec, signers); err != nil {
- log.Info("hey here1", "err", err, "utx", utx)
return nil, err
}
return tx, utx.Verify(vm.avm, vm.ctx, vm.txFee, vm.avaxAssetID)
diff --git a/plugin/evm/service.go b/plugin/evm/service.go
index 41cce50..86bc706 100644
--- a/plugin/evm/service.go
+++ b/plugin/evm/service.go
@@ -16,12 +16,11 @@ import (
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/gecko/api"
"github.com/ava-labs/gecko/utils/constants"
- avacrypto "github.com/ava-labs/gecko/utils/crypto"
+ "github.com/ava-labs/gecko/utils/crypto"
"github.com/ava-labs/gecko/utils/formatting"
"github.com/ava-labs/go-ethereum/common"
"github.com/ava-labs/go-ethereum/common/hexutil"
- "github.com/ava-labs/go-ethereum/crypto"
- "github.com/ava-labs/go-ethereum/log"
+ ethcrypto "github.com/ava-labs/go-ethereum/crypto"
)
const (
@@ -64,7 +63,7 @@ type Web3API struct{}
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) }
+func (s *Web3API) Sha3(input hexutil.Bytes) hexutil.Bytes { return ethcrypto.Keccak256(input) }
// GetAcceptedFrontReply defines the reply that will be sent from the
// GetAcceptedFront API call
@@ -101,7 +100,7 @@ func (api *DebugAPI) SpendGenesis(ctx context.Context, nonce uint64) error {
gasLimit := 21000
gasPrice := big.NewInt(1000000000)
- genPrivateKey, err := crypto.HexToECDSA(GenesisTestKey[2:])
+ genPrivateKey, err := ethcrypto.HexToECDSA(GenesisTestKey[2:])
if err != nil {
return err
}
@@ -180,7 +179,7 @@ func (service *AvaAPI) ImportKey(r *http.Request, args *ImportKeyArgs, reply *ap
user := user{db: db}
- factory := avacrypto.FactorySECP256K1R{}
+ factory := crypto.FactorySECP256K1R{}
if !strings.HasPrefix(args.PrivateKey, constants.SecretKeyPrefix) {
return fmt.Errorf("private key missing %s prefix", constants.SecretKeyPrefix)
@@ -195,7 +194,7 @@ func (service *AvaAPI) ImportKey(r *http.Request, args *ImportKeyArgs, reply *ap
if err != nil {
return fmt.Errorf("problem parsing private key: %w", err)
}
- sk := skIntf.(*avacrypto.PrivateKeySECP256K1R)
+ sk := skIntf.(*crypto.PrivateKeySECP256K1R)
if err := user.putAddress(sk); err != nil {
return fmt.Errorf("problem saving key %w", err)
@@ -203,7 +202,7 @@ func (service *AvaAPI) ImportKey(r *http.Request, args *ImportKeyArgs, reply *ap
// TODO: return eth address here
reply.Address, err = service.vm.FormatAddress(
- crypto.PubkeyToAddress(*(sk.PublicKey().(*avacrypto.PublicKeySECP256K1R).ToECDSA())))
+ ethcrypto.PubkeyToAddress(*(sk.PublicKey().(*crypto.PublicKeySECP256K1R).ToECDSA())))
if err != nil {
return fmt.Errorf("problem formatting address: %w", err)
}
@@ -254,6 +253,5 @@ func (service *AvaAPI) ImportAVAX(_ *http.Request, args *ImportAVAXArgs, respons
}
response.TxID = tx.ID()
- log.Info("hey here2")
return service.vm.issueTx(tx)
}
diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go
index 7cbfabd..baf6106 100644
--- a/plugin/evm/vm.go
+++ b/plugin/evm/vm.go
@@ -34,13 +34,11 @@ import (
"github.com/ava-labs/gecko/snow/choices"
"github.com/ava-labs/gecko/snow/consensus/snowman"
"github.com/ava-labs/gecko/utils/codec"
- "github.com/ava-labs/gecko/vms/secp256k1fx"
- //"github.com/ava-labs/gecko/utils/constants"
- //"github.com/ava-labs/gecko/utils/formatting"
avajson "github.com/ava-labs/gecko/utils/json"
"github.com/ava-labs/gecko/utils/timer"
"github.com/ava-labs/gecko/utils/wrappers"
"github.com/ava-labs/gecko/vms/components/avax"
+ "github.com/ava-labs/gecko/vms/secp256k1fx"
commonEng "github.com/ava-labs/gecko/snow/engine/common"
)
@@ -153,9 +151,9 @@ type VM struct {
}
func (vm *VM) getAtomicTx(block *types.Block) *Tx {
- var atx *Tx
+ atx := new(Tx)
if extdata := block.ExtraData(); extdata != nil {
- if err := vm.codec.Unmarshal(block.ExtraData(), atx); err != nil {
+ if err := vm.codec.Unmarshal(extdata, atx); err != nil {
panic(err)
}
}
@@ -212,19 +210,24 @@ func (vm *VM) Initialize(
}
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
- }
+ chain.SetOnFinalizeAndAssemble(func(state *state.StateDB, txs []*types.Transaction) ([]byte, error) {
select {
case atx := <-vm.pendingAtomicTxs:
+ for _, to := range atx.UnsignedTx.(*UnsignedImportTx).Outs {
+ amount := new(big.Int)
+ amount.SetUint64(to.Amount)
+ state.AddBalance(to.Address, amount)
+ }
raw, _ := vm.codec.Marshal(atx)
- block.SetExtraData(raw)
- // TODO: make sure the atomic Tx is valid
+ return raw, nil
+ default:
+ if len(txs) == 0 {
+ // this could happen due to the async logic of geth tx pool
+ vm.newBlockChan <- nil
+ return nil, errEmptyBlock
+ }
}
- return nil
+ return nil, nil
})
chain.SetOnSealFinish(func(block *types.Block) error {
vm.ctx.Log.Verbo("EVM sealed a block")
@@ -234,6 +237,9 @@ func (vm *VM) Initialize(
ethBlock: block,
vm: vm,
}
+ if blk.Verify() != nil {
+ return errInvalidBlock
+ }
vm.newBlockChan <- blk
vm.updateStatus(ids.NewID(block.Hash()), choices.Processing)
vm.txPoolStabilizedLock.Lock()
@@ -246,7 +252,6 @@ func (vm *VM) Initialize(
})
chain.SetOnExtraStateChange(func(block *types.Block, statedb *state.StateDB) error {
atx := vm.getAtomicTx(block).UnsignedTx.(*UnsignedImportTx)
- vm.ctx.Log.Info(atx.ID().String())
for _, to := range atx.Outs {
amount := new(big.Int)
amount.SetUint64(to.Amount)
@@ -282,6 +287,7 @@ func (vm *VM) Initialize(
vm.txPoolStabilizedOk = make(chan struct{}, 1)
// TODO: read size from options
vm.pendingAtomicTxs = make(chan *Tx, 1024)
+ vm.atomicTxSubmitChan = make(chan struct{}, 1)
chain.GetTxPool().SubscribeNewHeadEvent(vm.newTxPoolHeadChan)
// TODO: shutdown this go routine
go ctx.Log.RecoverAndPanic(func() {
@@ -523,7 +529,7 @@ func (vm *VM) tryBlockGen() error {
if err != nil {
return err
}
- if size == 0 {
+ if size == 0 && len(vm.pendingAtomicTxs) == 0 {
return nil
}
@@ -648,7 +654,10 @@ func (vm *VM) FormatAddress(addr common.Address) (string, error) {
func (vm *VM) issueTx(tx *Tx) error {
select {
case vm.pendingAtomicTxs <- tx:
- vm.atomicTxSubmitChan <- struct{}{}
+ select {
+ case vm.atomicTxSubmitChan <- struct{}{}:
+ default:
+ }
default:
return errTooManyAtomicTx
}
@@ -666,7 +675,8 @@ func (vm *VM) GetAtomicUTXOs(
) ([]*avax.UTXO, ids.ShortID, ids.ID, error) {
// TODO: finish this function via gRPC
utxos := []*avax.UTXO{{
- Asset: avax.Asset{ID: vm.ctx.AVAXAssetID},
+ UTXOID: avax.UTXOID{TxID: ids.Empty},
+ Asset: avax.Asset{ID: vm.ctx.AVAXAssetID},
Out: &secp256k1fx.TransferOutput{
Amt: 100,
},