From 1e9599e88a5d88e0090b0ebddfae756e343e605a Mon Sep 17 00:00:00 2001 From: Determinant Date: Wed, 19 Aug 2020 20:32:18 -0400 Subject: make the basic X-to-C logic work --- plugin/evm/block.go | 2 +- plugin/evm/import_tx.go | 13 ++++--------- plugin/evm/service.go | 16 +++++++--------- plugin/evm/vm.go | 46 ++++++++++++++++++++++++++++------------------ 4 files changed, 40 insertions(+), 37 deletions(-) (limited to 'plugin/evm') 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, }, -- cgit v1.2.3-70-g09d2