From b93406a68fa2610eaa473152f4a113831bd5bf67 Mon Sep 17 00:00:00 2001 From: Jonathan Downing Date: Thu, 1 Feb 2024 13:50:55 +1100 Subject: [PATCH 1/2] Refactored precompile addresses to be QIP2 compatible --- common/address.go | 15 ++++- common/types_test.go | 3 + core/vm/contracts.go | 134 ++++--------------------------------------- core/vm/evm.go | 12 +++- 4 files changed, 36 insertions(+), 128 deletions(-) diff --git a/common/address.go b/common/address.go index 89d6f51614..e2388a4cd6 100644 --- a/common/address.go +++ b/common/address.go @@ -20,7 +20,7 @@ type Address struct { inner AddressData } -type AddressBytes [20]byte +type AddressBytes [AddressLength]byte type AddressData interface { Bytes() []byte @@ -257,6 +257,19 @@ func HexToAddress(s string, nodeLocation Location) Address { return BytesToAddress(FromHex(s), nodeLocation) } +func HexToAddressBytes(s string) AddressBytes { + var a AddressBytes + a.SetBytes(FromHex(s)) + return a +} + +func (a *AddressBytes) SetBytes(b []byte) { + if len(b) > len(a) { + b = b[len(b)-AddressLength:] + } + copy(a[AddressLength-len(b):], b) +} + // IsHexAddress verifies whether a string can represent a valid hex-encoded // Quai address or not. func IsHexAddress(s string) bool { diff --git a/common/types_test.go b/common/types_test.go index 733b39e294..ebbbf32a9b 100644 --- a/common/types_test.go +++ b/common/types_test.go @@ -537,6 +537,9 @@ func TestHash_Format(t *testing.T) { } func TestZeroAddress(t *testing.T) { + t.Log(fmt.Sprintf("0x%x00000000000000000000000000000000000000", nodeLocation.BytePrefix())) + addr := HexToAddress("0x110000000000000000000000000000000000115", nodeLocation) + t.Log(fmt.Sprintf("0x%x000000000000000000000000000000000000%02x", nodeLocation.BytePrefix(), addr.Bytes20()[19])) t.Log(ZeroAddress(nodeLocation).String()) internal, err := ZeroAddress(nodeLocation).InternalAddress() if err != nil { diff --git a/core/vm/contracts.go b/core/vm/contracts.go index c5857569e4..bdc09d1b65 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -20,6 +20,7 @@ import ( "crypto/sha256" "encoding/binary" "errors" + "fmt" "math/big" "github.com/dominant-strategies/go-quai/common" @@ -41,136 +42,21 @@ type PrecompiledContract interface { Run(input []byte) ([]byte, error) // Run runs the precompiled contract } -var TranslatedAddresses = map[common.AddressBytes]int{ - common.AddressBytes(intToByteArray20(1)): 0, - common.AddressBytes(intToByteArray20(2)): 1, - common.AddressBytes(intToByteArray20(3)): 2, - common.AddressBytes(intToByteArray20(4)): 3, - common.AddressBytes(intToByteArray20(5)): 4, - common.AddressBytes(intToByteArray20(6)): 5, - common.AddressBytes(intToByteArray20(7)): 6, - common.AddressBytes(intToByteArray20(8)): 7, - common.AddressBytes(intToByteArray20(9)): 8, -} - var ( PrecompiledContracts map[common.AddressBytes]PrecompiledContract = make(map[common.AddressBytes]PrecompiledContract) PrecompiledAddresses map[string][]common.Address = make(map[string][]common.Address) ) func InitializePrecompiles(nodeLocation common.Location) { - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][0].Bytes20()] = &ecrecover{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][1].Bytes20()] = &sha256hash{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][2].Bytes20()] = &ripemd160hash{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][3].Bytes20()] = &dataCopy{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][4].Bytes20()] = &bigModExp{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][5].Bytes20()] = &bn256Add{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][6].Bytes20()] = &bn256ScalarMul{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][7].Bytes20()] = &bn256Pairing{} - PrecompiledContracts[PrecompiledAddresses[nodeLocation.Name()][8].Bytes20()] = &blake2F{} -} - -func init() { - - PrecompiledAddresses["cyprus1"] = []common.Address{ - common.HexToAddress("0x1400000000000000000000000000000000000001", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000002", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000003", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000004", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000005", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000006", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000007", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000008", common.Location{0, 0}), - common.HexToAddress("0x1400000000000000000000000000000000000009", common.Location{0, 0}), - } - PrecompiledAddresses["cyprus2"] = []common.Address{ - common.HexToAddress("0x2000000000000000000000000000000000000001", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000002", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000003", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000004", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000005", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000006", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000007", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000008", common.Location{0, 1}), - common.HexToAddress("0x2000000000000000000000000000000000000009", common.Location{0, 1}), - } - PrecompiledAddresses["cyprus3"] = []common.Address{ - common.HexToAddress("0x3E00000000000000000000000000000000000001", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000002", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000003", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000004", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000005", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000006", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000007", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000008", common.Location{0, 2}), - common.HexToAddress("0x3E00000000000000000000000000000000000009", common.Location{0, 2}), - } - PrecompiledAddresses["paxos1"] = []common.Address{ - common.HexToAddress("0x5A00000000000000000000000000000000000001", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000002", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000003", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000004", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000005", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000006", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000007", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000008", common.Location{1, 0}), - common.HexToAddress("0x5A00000000000000000000000000000000000009", common.Location{1, 0}), - } - PrecompiledAddresses["paxos2"] = []common.Address{ - common.HexToAddress("0x7800000000000000000000000000000000000001", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000002", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000003", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000004", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000005", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000006", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000007", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000008", common.Location{1, 1}), - common.HexToAddress("0x7800000000000000000000000000000000000009", common.Location{1, 1}), - } - PrecompiledAddresses["paxos3"] = []common.Address{ - common.HexToAddress("0x9600000000000000000000000000000000000001", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000002", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000003", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000004", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000005", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000006", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000007", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000008", common.Location{1, 2}), - common.HexToAddress("0x9600000000000000000000000000000000000009", common.Location{1, 2}), - } - PrecompiledAddresses["hydra1"] = []common.Address{ - common.HexToAddress("0xB400000000000000000000000000000000000001", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000002", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000003", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000004", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000005", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000006", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000007", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000008", common.Location{2, 0}), - common.HexToAddress("0xB400000000000000000000000000000000000009", common.Location{2, 0}), - } - PrecompiledAddresses["hydra2"] = []common.Address{ - common.HexToAddress("0xD200000000000000000000000000000000000001", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000002", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000003", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000004", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000005", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000006", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000007", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000008", common.Location{2, 1}), - common.HexToAddress("0xD200000000000000000000000000000000000009", common.Location{2, 1}), - } - PrecompiledAddresses["hydra3"] = []common.Address{ - common.HexToAddress("0xF000000000000000000000000000000000000001", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000002", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000003", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000004", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000005", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000006", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000007", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000008", common.Location{2, 2}), - common.HexToAddress("0xF000000000000000000000000000000000000009", common.Location{2, 2}), - } + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000001", nodeLocation.BytePrefix()))] = &ecrecover{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000002", nodeLocation.BytePrefix()))] = &sha256hash{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000003", nodeLocation.BytePrefix()))] = &ripemd160hash{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000004", nodeLocation.BytePrefix()))] = &dataCopy{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000005", nodeLocation.BytePrefix()))] = &bigModExp{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000006", nodeLocation.BytePrefix()))] = &bn256Add{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000007", nodeLocation.BytePrefix()))] = &bn256ScalarMul{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000008", nodeLocation.BytePrefix()))] = &bn256Pairing{} + PrecompiledContracts[common.HexToAddressBytes(fmt.Sprintf("0x%x00000000000000000000000000000000000009", nodeLocation.BytePrefix()))] = &blake2F{} } // ActivePrecompiles returns the precompiles enabled with the current configuration. diff --git a/core/vm/evm.go b/core/vm/evm.go index d00d09f494..86982da6a9 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -47,10 +47,16 @@ type ( ) func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool, common.Address) { - if index, ok := TranslatedAddresses[addr.Bytes20()]; ok { - addr = PrecompiledAddresses[evm.chainConfig.Location.Name()][index] - } p, ok := PrecompiledContracts[addr.Bytes20()] + if !ok { + // to translate the address, we add the last byte of the address to the location-specific zero address + // to support more than 255 precompiles, we could use the last two bytes, but it's likely unnecessary + translatedAddress := common.HexToAddressBytes(fmt.Sprintf("0x%x000000000000000000000000000000000000%02x", evm.chainConfig.Location.BytePrefix(), addr.Bytes20()[19])) + p, ok = PrecompiledContracts[translatedAddress] + if ok { + addr = common.Bytes20ToAddress(translatedAddress, evm.chainConfig.Location) + } + } return p, ok, addr } From 69f4640ff9cc26239b9aeccb45efda9da61bfd01 Mon Sep 17 00:00:00 2001 From: Jonathan Downing Date: Wed, 28 Feb 2024 19:12:57 -0600 Subject: [PATCH 2/2] Bugfixes in transaction encode/decode and empty slice checks --- core/headerchain.go | 4 ++-- core/state_processor.go | 6 +++--- core/types/stxo.go | 2 +- core/types/transaction.go | 28 ++++++++++++++++++++-------- core/worker.go | 14 +++++++++----- internal/quaiapi/api.go | 8 +++++++- quai/api_backend.go | 3 +++ quaiclient/ethclient/ethclient.go | 7 ++++++- 8 files changed, 51 insertions(+), 21 deletions(-) diff --git a/core/headerchain.go b/core/headerchain.go index 85fdc22db5..4f26f0ef17 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -1249,7 +1249,7 @@ func (hc *HeaderChain) fetchInputUtxos(view *types.UtxoViewpoint, block *types.B txInFlight[tx.Hash()] = i } - if types.IsCoinBaseTx(transactions[0]) { + if len(transactions) > 0 && types.IsCoinBaseTx(transactions[0]) { transactions = transactions[1:] } @@ -1296,7 +1296,7 @@ func (hc *HeaderChain) fetchInputUtxos(view *types.UtxoViewpoint, block *types.B func (hc *HeaderChain) verifyInputUtxos(view *types.UtxoViewpoint, block *types.Block, signer types.Signer) (*big.Int, error) { // should this be used instead of Verify transactions := block.QiTransactions() - if types.IsCoinBaseTx(transactions[0]) { + if len(transactions) > 0 && types.IsCoinBaseTx(transactions[0]) { transactions = transactions[1:] } diff --git a/core/state_processor.go b/core/state_processor.go index d36081d21f..d7b19b3713 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -332,7 +332,7 @@ func (p *StateProcessor) Process(block *types.Block, etxSet types.EtxSet) (types i++ } - if types.IsCoinBaseTx(block.QiTransactions()[0]) { + if len(block.QiTransactions()) > 0 && types.IsCoinBaseTx(block.QiTransactions()[0]) { totalCoinbaseOut := big.NewInt(0) for _, txOut := range block.QiTransactions()[0].TxOut() { totalCoinbaseOut.Add(totalCoinbaseOut, types.Denominations[txOut.Denomination]) @@ -911,7 +911,7 @@ func (p *StateProcessor) FetchInputUtxos(statedb *state.StateDB, view *types.Utx for i, tx := range transactions { txInFlight[tx.Hash()] = i } - if types.IsCoinBaseTx(transactions[0]) { + if len(transactions) > 0 && types.IsCoinBaseTx(transactions[0]) { transactions = transactions[1:] } // Loop through all of the transaction inputs (except for the coinbase @@ -957,7 +957,7 @@ func (p *StateProcessor) FetchInputUtxos(statedb *state.StateDB, view *types.Utx func (p *StateProcessor) VerifyTransactions(view *types.UtxoViewpoint, block *types.Block, signer types.Signer) (*big.Int, error) { transactions := block.QiTransactions() - if types.IsCoinBaseTx(transactions[0]) { + if len(transactions) > 0 && types.IsCoinBaseTx(transactions[0]) { transactions = transactions[1:] } diff --git a/core/types/stxo.go b/core/types/stxo.go index b899653522..32b7ce6067 100644 --- a/core/types/stxo.go +++ b/core/types/stxo.go @@ -27,7 +27,7 @@ func CountSpentOutputs(block *Block) int { if len(transactions) == 0 { return 0 } - if IsCoinBaseTx(transactions[0]) { + if len(transactions) > 0 && IsCoinBaseTx(transactions[0]) { transactions = transactions[1:] } // Exclude the coinbase transaction since it can't spend anything. diff --git a/core/types/transaction.go b/core/types/transaction.go index ebd502cd38..7ea11bfedf 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -134,7 +134,11 @@ func (tx *Transaction) ProtoEncode() (*ProtoTransaction, error) { protoTx.Gas = &gas protoTx.AccessList = tx.AccessList().ProtoEncode() protoTx.Value = tx.Value().Bytes() - protoTx.Data = tx.Data() + if tx.Data() == nil { + protoTx.Data = []byte{} + } else { + protoTx.Data = tx.Data() + } if tx.To() != nil { protoTx.To = tx.To().Bytes() } @@ -216,15 +220,15 @@ func (tx *Transaction) ProtoDecode(protoTx *ProtoTransaction, location common.Lo if protoTx.Value == nil { return errors.New("missing required field 'Value' in ProtoTransaction") } - if protoTx.Data == nil { - return errors.New("missing required field 'Data' in ProtoTransaction") - } if protoTx.GasFeeCap == nil { return errors.New("missing required field 'GasFeeCap' in ProtoTransaction") } if protoTx.GasTipCap == nil { return errors.New("missing required field 'GasTipCap' in ProtoTransaction") } + if protoTx.Data == nil { + return errors.New("missing required field 'Data' in ProtoTransaction") + } var itx InternalTx itx.AccessList = AccessList{} itx.AccessList.ProtoDecode(protoTx.GetAccessList(), location) @@ -239,7 +243,11 @@ func (tx *Transaction) ProtoDecode(protoTx *ProtoTransaction, location common.Lo itx.GasTipCap = new(big.Int).SetBytes(protoTx.GetGasTipCap()) itx.GasFeeCap = new(big.Int).SetBytes(protoTx.GetGasFeeCap()) itx.Gas = protoTx.GetGas() - itx.Value = new(big.Int).SetBytes(protoTx.GetValue()) + if len(protoTx.GetValue()) == 0 { + itx.Value = common.Big0 + } else { + itx.Value = new(big.Int).SetBytes(protoTx.GetValue()) + } itx.Data = protoTx.GetData() if protoTx.V == nil { return errors.New("missing required field 'V' in InternalTx") @@ -431,11 +439,15 @@ func (tx *Transaction) ProtoEncodeTxSigningData() *ProtoTransaction { protoTxSigningData.Gas = &gas protoTxSigningData.AccessList = tx.AccessList().ProtoEncode() protoTxSigningData.Value = tx.Value().Bytes() - protoTxSigningData.Data = tx.Data() - if tx.To() != nil { - protoTxSigningData.To = tx.To().Bytes() + if tx.Data() == nil { + protoTxSigningData.Data = []byte{} } else { + protoTxSigningData.Data = tx.Data() + } + if tx.To() == nil { protoTxSigningData.To = []byte{} + } else { + protoTxSigningData.To = tx.To().Bytes() } protoTxSigningData.GasFeeCap = tx.GasFeeCap().Bytes() protoTxSigningData.GasTipCap = tx.GasTipCap().Bytes() diff --git a/core/worker.go b/core/worker.go index 7fe45be489..a5c064c00b 100644 --- a/core/worker.go +++ b/core/worker.go @@ -545,7 +545,9 @@ func (w *worker) GeneratePendingHeader(block *types.Block, fill bool) (*types.He } if nodeCtx == common.ZONE_CTX && w.hc.ProcessingState() { - work.txs = append(work.txs, types.NewTx(&types.QiTx{})) // placeholder + if coinbase.IsInQiLedgerScope() { + work.txs = append(work.txs, types.NewTx(&types.QiTx{})) // placeholder + } // Fill pending transactions from the txpool w.adjustGasLimit(nil, work, block) work.utxoFees = big.NewInt(0) @@ -559,11 +561,13 @@ func (w *worker) GeneratePendingHeader(block *types.Block, fill bool) (*types.He "average": common.PrettyDuration(w.fillTransactionsRollingAverage.Average()), }).Info("Filled and sorted pending transactions") } - coinbaseTx, err := createCoinbaseTxWithFees(work.header, work.utxoFees, work.state) - if err != nil { - return nil, err + if coinbase.IsInQiLedgerScope() { + coinbaseTx, err := createCoinbaseTxWithFees(work.header, work.utxoFees, work.state) + if err != nil { + return nil, err + } + work.txs[0] = coinbaseTx } - work.txs[0] = coinbaseTx } // Create a local environment copy, avoid the data race with snapshot state. diff --git a/internal/quaiapi/api.go b/internal/quaiapi/api.go index 0b46143ea6..ce9cf12168 100644 --- a/internal/quaiapi/api.go +++ b/internal/quaiapi/api.go @@ -1496,6 +1496,9 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha // SubmitTransaction is a helper function that submits tx to txPool and logs a message. func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) { + if tx == nil { + return common.Hash{}, errors.New("transaction is nil") + } nodeLocation := b.NodeLocation() nodeCtx := b.NodeCtx() if nodeCtx != common.ZONE_CTX { @@ -1555,7 +1558,10 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, input if err != nil { return common.Hash{}, err } - tx.ProtoDecode(protoTransaction, s.b.NodeLocation()) + err = tx.ProtoDecode(protoTransaction, s.b.NodeLocation()) + if err != nil { + return common.Hash{}, err + } return SubmitTransaction(ctx, s.b, tx) } diff --git a/quai/api_backend.go b/quai/api_backend.go index 23bc7c3083..712ae1db17 100644 --- a/quai/api_backend.go +++ b/quai/api_backend.go @@ -348,6 +348,9 @@ func (b *QuaiAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) return nil, common.Hash{}, 0, 0, errors.New("getTransaction can only be called in zone chain") } tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.quai.ChainDb(), txHash, b.NodeLocation()) + if tx == nil { + return nil, common.Hash{}, 0, 0, errors.New("transaction not found") + } return tx, blockHash, blockNumber, index, nil } diff --git a/quaiclient/ethclient/ethclient.go b/quaiclient/ethclient/ethclient.go index b5ea7b77af..d501b064f6 100644 --- a/quaiclient/ethclient/ethclient.go +++ b/quaiclient/ethclient/ethclient.go @@ -29,6 +29,7 @@ import ( "github.com/dominant-strategies/go-quai/common/hexutil" "github.com/dominant-strategies/go-quai/core/types" "github.com/dominant-strategies/go-quai/rpc" + "google.golang.org/protobuf/proto" ) // Client defines typed wrappers for the Quai RPC API. @@ -504,7 +505,11 @@ func (ec *Client) EstimateGas(ctx context.Context, msg quai.CallMsg) (uint64, er // If the transaction was a contract creation use the TransactionReceipt method to get the // contract address after the transaction has been mined. func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error { - data, err := tx.MarshalBinary() + protoTx, err := tx.ProtoEncode() + if err != nil { + return err + } + data, err := proto.Marshal(protoTx) if err != nil { return err }