From 5c93efd4664f5b682a0f62f979a67ebf4658630a Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Fri, 5 Mar 2021 22:21:05 -0800 Subject: [PATCH 01/10] Add raw transaction to tx meta --- core/rawdb/accessors_chain_test.go | 4 +- core/rawdb/accessors_indexes_test.go | 6 +- core/types/transaction.go | 2 +- core/types/transaction_meta.go | 21 ++++++- core/types/transaction_meta_test.go | 81 ++++++++++++++------------ core/types/transaction_signing_test.go | 6 +- internal/ethapi/api.go | 8 +-- rollup/client.go | 3 + rollup/sync_service_test.go | 3 + signer/core/types.go | 2 +- 10 files changed, 83 insertions(+), 53 deletions(-) diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index c3a7203bc..3c1ffa065 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -430,7 +430,7 @@ func TestBlockMetaStorage(t *testing.T) { index1 := uint64(1) tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil) - tx1Meta := types.NewTransactionMeta(nil, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, &index1, nil) + tx1Meta := types.NewTransactionMeta(nil, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, &index1, nil, nil) tx1.SetTransactionMeta(tx1Meta) WriteTransactionMeta(db, index1, tx1.GetMeta()) @@ -464,7 +464,7 @@ func TestBlockMetaStorage(t *testing.T) { index2 := uint64(2) tx2 := types.NewTransaction(2, common.HexToAddress("0x02"), big.NewInt(2), 2, big.NewInt(2), nil) - tx2Meta := types.NewTransactionMeta(l1BlockNumber, 0, &addr, types.SighashEthSign, types.QueueOriginSequencer, nil, nil) + tx2Meta := types.NewTransactionMeta(l1BlockNumber, 0, &addr, types.SighashEthSign, types.QueueOriginSequencer, nil, nil, nil) tx2.SetTransactionMeta(tx2Meta) WriteTransactionMeta(db, index2, tx2.GetMeta()) diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go index 6c3ddd242..f980bcf20 100644 --- a/core/rawdb/accessors_indexes_test.go +++ b/core/rawdb/accessors_indexes_test.go @@ -73,15 +73,15 @@ func TestLookupStorage(t *testing.T) { l1BlockNumber2 := big.NewInt(2) tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) - tx1Meta := types.NewTransactionMeta(l1BlockNumber1, 0, &sender1, types.SighashEIP155, types.QueueOriginSequencer, nil, nil) + tx1Meta := types.NewTransactionMeta(l1BlockNumber1, 0, &sender1, types.SighashEIP155, types.QueueOriginSequencer, nil, nil, nil) tx1.SetTransactionMeta(tx1Meta) tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}) - tx2Meta := types.NewTransactionMeta(l1BlockNumber2, 0, &sender2, types.SighashEIP155, types.QueueOriginSequencer, nil, nil) + tx2Meta := types.NewTransactionMeta(l1BlockNumber2, 0, &sender2, types.SighashEIP155, types.QueueOriginSequencer, nil, nil, nil) tx2.SetTransactionMeta(tx2Meta) tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}) - tx3Meta := types.NewTransactionMeta(l1BlockNumber1, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, nil, nil) + tx3Meta := types.NewTransactionMeta(l1BlockNumber1, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, nil, nil, nil) tx3.SetTransactionMeta(tx3Meta) txs := []*types.Transaction{tx1, tx2, tx3} diff --git a/core/types/transaction.go b/core/types/transaction.go index b33fa78cb..3aaf1c3c2 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -95,7 +95,7 @@ func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit data = common.CopyBytes(data) } - meta := NewTransactionMeta(nil, 0, nil, SighashEIP155, QueueOriginSequencer, nil, nil) + meta := NewTransactionMeta(nil, 0, nil, SighashEIP155, QueueOriginSequencer, nil, nil, nil) d := txdata{ AccountNonce: nonce, diff --git a/core/types/transaction_meta.go b/core/types/transaction_meta.go index bacd6d86b..a475c53de 100644 --- a/core/types/transaction_meta.go +++ b/core/types/transaction_meta.go @@ -31,11 +31,12 @@ type TransactionMeta struct { // The canonical transaction chain index Index *uint64 `json:"index" gencodec:"required"` // The queue index, nil for queue origin sequencer transactions - QueueIndex *uint64 `json:"queueIndex" gencodec:"required"` + QueueIndex *uint64 `json:"queueIndex" gencodec:"required"` + RawTransaction []byte `json:"rawTransaction" gencodec:"required"` } // NewTransactionMeta creates a TransactionMeta -func NewTransactionMeta(l1BlockNumber *big.Int, l1timestamp uint64, l1MessageSender *common.Address, sighashType SignatureHashType, queueOrigin QueueOrigin, index *uint64, queueIndex *uint64) *TransactionMeta { +func NewTransactionMeta(l1BlockNumber *big.Int, l1timestamp uint64, l1MessageSender *common.Address, sighashType SignatureHashType, queueOrigin QueueOrigin, index *uint64, queueIndex *uint64, rawTransaction []byte) *TransactionMeta { return &TransactionMeta{ L1BlockNumber: l1BlockNumber, L1Timestamp: l1timestamp, @@ -44,6 +45,7 @@ func NewTransactionMeta(l1BlockNumber *big.Int, l1timestamp uint64, l1MessageSen QueueOrigin: big.NewInt(int64(queueOrigin)), Index: index, QueueIndex: queueIndex, + RawTransaction: rawTransaction, } } @@ -121,6 +123,14 @@ func TxMetaDecode(input []byte) (*TransactionMeta, error) { meta.QueueIndex = &queueIndex } + raw, err := common.ReadVarBytes(b, 0, 130000, "RawTransaction") + if err != nil { + return nil, err + } + if !isNullValue(raw) { + meta.RawTransaction = raw + } + return &meta, nil } @@ -181,6 +191,13 @@ func TxMetaEncode(meta *TransactionMeta) []byte { common.WriteVarBytes(b, 0, qi.Bytes()) } + rawTransaction := meta.RawTransaction + if rawTransaction == nil { + common.WriteVarBytes(b, 0, getNullValue()) + } else { + common.WriteVarBytes(b, 0, rawTransaction) + } + return b.Bytes() } diff --git a/core/types/transaction_meta_test.go b/core/types/transaction_meta_test.go index 1fc23716a..6471b5f77 100644 --- a/core/types/transaction_meta_test.go +++ b/core/types/transaction_meta_test.go @@ -14,53 +14,60 @@ var ( l1BlockNumber = big.NewInt(0) txMetaSerializationTests = []struct { - l1BlockNumber *big.Int - l1Timestamp uint64 - msgSender *common.Address - sighashType SignatureHashType - queueOrigin QueueOrigin + l1BlockNumber *big.Int + l1Timestamp uint64 + msgSender *common.Address + sighashType SignatureHashType + queueOrigin QueueOrigin + rawTransaction []byte }{ { - l1BlockNumber: l1BlockNumber, - l1Timestamp: 100, - msgSender: &addr, - sighashType: SighashEthSign, - queueOrigin: QueueOriginL1ToL2, + l1BlockNumber: l1BlockNumber, + l1Timestamp: 100, + msgSender: &addr, + sighashType: SighashEthSign, + queueOrigin: QueueOriginL1ToL2, + rawTransaction: []byte{255, 255, 255, 255}, }, { - l1BlockNumber: nil, - l1Timestamp: 45, - msgSender: &addr, - sighashType: SighashEthSign, - queueOrigin: QueueOriginL1ToL2, + l1BlockNumber: nil, + l1Timestamp: 45, + msgSender: &addr, + sighashType: SighashEthSign, + queueOrigin: QueueOriginL1ToL2, + rawTransaction: []byte{42, 69, 42, 69}, }, { - l1BlockNumber: l1BlockNumber, - l1Timestamp: 0, - msgSender: nil, - sighashType: SighashEthSign, - queueOrigin: QueueOriginSequencer, + l1BlockNumber: l1BlockNumber, + l1Timestamp: 0, + msgSender: nil, + sighashType: SighashEthSign, + queueOrigin: QueueOriginSequencer, + rawTransaction: []byte{0, 0, 0, 0}, }, { - l1BlockNumber: l1BlockNumber, - l1Timestamp: 0, - msgSender: &addr, - sighashType: SighashEthSign, - queueOrigin: QueueOriginSequencer, + l1BlockNumber: l1BlockNumber, + l1Timestamp: 0, + msgSender: &addr, + sighashType: SighashEthSign, + queueOrigin: QueueOriginSequencer, + rawTransaction: []byte{0, 0, 0, 0}, }, { - l1BlockNumber: nil, - l1Timestamp: 0, - msgSender: nil, - sighashType: SighashEthSign, - queueOrigin: QueueOriginL1ToL2, + l1BlockNumber: nil, + l1Timestamp: 0, + msgSender: nil, + sighashType: SighashEthSign, + queueOrigin: QueueOriginL1ToL2, + rawTransaction: []byte{0, 0, 0, 0}, }, { - l1BlockNumber: l1BlockNumber, - l1Timestamp: 0, - msgSender: &addr, - sighashType: SighashEthSign, - queueOrigin: QueueOriginL1ToL2, + l1BlockNumber: l1BlockNumber, + l1Timestamp: 0, + msgSender: &addr, + sighashType: SighashEthSign, + queueOrigin: QueueOriginL1ToL2, + rawTransaction: []byte{0, 0, 0, 0}, }, } @@ -81,7 +88,7 @@ var ( func TestTransactionMetaEncode(t *testing.T) { for _, test := range txMetaSerializationTests { - txmeta := NewTransactionMeta(test.l1BlockNumber, test.l1Timestamp, test.msgSender, test.sighashType, test.queueOrigin, nil, nil) + txmeta := NewTransactionMeta(test.l1BlockNumber, test.l1Timestamp, test.msgSender, test.sighashType, test.queueOrigin, nil, nil, test.rawTransaction) encoded := TxMetaEncode(txmeta) decoded, err := TxMetaDecode(encoded) @@ -98,7 +105,7 @@ func TestTransactionMetaEncode(t *testing.T) { func TestTransactionSighashEncode(t *testing.T) { for _, test := range txMetaSighashEncodeTests { - txmeta := NewTransactionMeta(l1BlockNumber, 0, &addr, test.input, QueueOriginSequencer, nil, nil) + txmeta := NewTransactionMeta(l1BlockNumber, 0, &addr, test.input, QueueOriginSequencer, nil, nil, nil) encoded := TxMetaEncode(txmeta) decoded, err := TxMetaDecode(encoded) diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go index 42898015a..f0102710b 100644 --- a/core/types/transaction_signing_test.go +++ b/core/types/transaction_signing_test.go @@ -141,7 +141,7 @@ func TestOVMSigner(t *testing.T) { key, _ := defaultTestKey() tx := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil) - txMeta := NewTransactionMeta(nil, 0, nil, SighashEthSign, QueueOriginSequencer, nil, nil) + txMeta := NewTransactionMeta(nil, 0, nil, SighashEthSign, QueueOriginSequencer, nil, nil, nil) tx.SetTransactionMeta(txMeta) var err error @@ -175,7 +175,7 @@ func TestOVMSignerHash(t *testing.T) { // The signature hash should be different when using `SighashEthSign` txEthSign := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil) - txMeta := NewTransactionMeta(nil, 0, nil, SighashEthSign, QueueOriginSequencer, nil, nil) + txMeta := NewTransactionMeta(nil, 0, nil, SighashEthSign, QueueOriginSequencer, nil, nil, nil) txEthSign.SetTransactionMeta(txMeta) hashEthSign := signer.Hash(txEthSign) @@ -216,7 +216,7 @@ func TestOVMSignerSender(t *testing.T) { // Create a transaction with EthSign signature hash, sign the transaction, // recover the address and assert that the address matches the key. txEthSign := NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil) - txMeta := NewTransactionMeta(nil, 0, nil, SighashEthSign, QueueOriginSequencer, nil, nil) + txMeta := NewTransactionMeta(nil, 0, nil, SighashEthSign, QueueOriginSequencer, nil, nil, nil) txEthSign.SetTransactionMeta(txMeta) txEthSign, err = SignTx(txEthSign, signer, key) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 6324c2c15..231b6b4e6 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1547,12 +1547,12 @@ func (args *SendTxArgs) toTransaction() *types.Transaction { } if args.To == nil { tx := types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input) - txMeta := types.NewTransactionMeta(args.L1BlockNumber, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, nil, nil) + txMeta := types.NewTransactionMeta(args.L1BlockNumber, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, nil, nil, nil) tx.SetTransactionMeta(txMeta) return tx } tx := types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input) - txMeta := types.NewTransactionMeta(args.L1BlockNumber, 0, args.L1MessageSender, args.SignatureHashType, types.QueueOriginSequencer, nil, nil) + txMeta := types.NewTransactionMeta(args.L1BlockNumber, 0, args.L1MessageSender, args.SignatureHashType, types.QueueOriginSequencer, nil, nil, nil) tx.SetTransactionMeta(txMeta) return tx } @@ -1651,7 +1651,7 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod return common.Hash{}, errors.New("Gas price must be a multiple of 1,000,000 wei") } // L1Timestamp and L1BlockNumber will be set by the miner - txMeta := types.NewTransactionMeta(nil, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, nil, nil) + txMeta := types.NewTransactionMeta(nil, 0, nil, types.SighashEIP155, types.QueueOriginSequencer, nil, nil, nil) tx.SetTransactionMeta(txMeta) return SubmitTransaction(ctx, s.b, tx) } @@ -1678,7 +1678,7 @@ func (s *PublicTransactionPoolAPI) SendRawEthSignTransaction(ctx context.Context return common.Hash{}, errors.New("Gas price must be a multiple of 1,000,000 wei") } // L1Timestamp and L1BlockNumber will be set by the miner - txMeta := types.NewTransactionMeta(nil, 0, nil, types.SighashEthSign, types.QueueOriginSequencer, nil, nil) + txMeta := types.NewTransactionMeta(nil, 0, nil, types.SighashEthSign, types.QueueOriginSequencer, nil, nil, nil) tx.SetTransactionMeta(txMeta) return SubmitTransaction(ctx, s.b, tx) } diff --git a/rollup/client.go b/rollup/client.go index 903417346..5a3194320 100644 --- a/rollup/client.go +++ b/rollup/client.go @@ -191,6 +191,7 @@ func enqueueToTransaction(enqueue *Enqueue) (*types.Transaction, error) { types.QueueOriginL1ToL2, enqueue.Index, enqueue.QueueIndex, + nil, // TODO: UPDATE THIS ) tx.SetTransactionMeta(txMeta) @@ -271,6 +272,7 @@ func transactionResponseToTransaction(res *TransactionResponse, signer *types.OV queueOrigin, &res.Transaction.Index, res.Transaction.QueueIndex, + nil, // TODO: UPDATE THIS ) tx.SetTransactionMeta(txMeta) @@ -310,6 +312,7 @@ func transactionResponseToTransaction(res *TransactionResponse, signer *types.OV queueOrigin, &res.Transaction.Index, res.Transaction.QueueIndex, + nil, // TODO: UPDATE THIS ) tx.SetTransactionMeta(txMeta) return tx, nil diff --git a/rollup/sync_service_test.go b/rollup/sync_service_test.go index fcef28bf2..1d7a18185 100644 --- a/rollup/sync_service_test.go +++ b/rollup/sync_service_test.go @@ -53,6 +53,7 @@ func TestSyncServiceTransactionEnqueued(t *testing.T) { types.QueueOriginL1ToL2, &index, &queueIndex, + nil, ) tx.SetTransactionMeta(txMeta) @@ -104,6 +105,7 @@ func TestSyncServiceSync(t *testing.T) { types.QueueOriginL1ToL2, &index, &queueIndex, + nil, ) tx.SetTransactionMeta(txMeta) @@ -149,6 +151,7 @@ func TestInitializeL1ContextPostGenesis(t *testing.T) { types.QueueOriginL1ToL2, &index, &queueIndex, + nil, ) tx.SetTransactionMeta(txMeta) diff --git a/signer/core/types.go b/signer/core/types.go index 179b7aee3..28ccea210 100644 --- a/signer/core/types.go +++ b/signer/core/types.go @@ -111,7 +111,7 @@ func (args *SendTxArgs) toTransaction() *types.Transaction { } tx := types.NewTransaction(uint64(args.Nonce), args.To.Address(), (*big.Int)(&args.Value), (uint64)(args.Gas), (*big.Int)(&args.GasPrice), input) - txMeta := types.NewTransactionMeta(l1BlockNumber, 0, l1MessageSender, args.SignatureHashType, args.QueueOrigin, nil, nil) + txMeta := types.NewTransactionMeta(l1BlockNumber, 0, l1MessageSender, args.SignatureHashType, args.QueueOrigin, nil, nil, nil) tx.SetTransactionMeta(txMeta) return tx } From 0187a0459a284a6693ecb228a951eecf7b3d193e Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Fri, 5 Mar 2021 22:29:11 -0800 Subject: [PATCH 02/10] Add data to client --- rollup/client.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rollup/client.go b/rollup/client.go index 5a3194320..e2d9b4757 100644 --- a/rollup/client.go +++ b/rollup/client.go @@ -191,7 +191,7 @@ func enqueueToTransaction(enqueue *Enqueue) (*types.Transaction, error) { types.QueueOriginL1ToL2, enqueue.Index, enqueue.QueueIndex, - nil, // TODO: UPDATE THIS + data, ) tx.SetTransactionMeta(txMeta) @@ -272,7 +272,7 @@ func transactionResponseToTransaction(res *TransactionResponse, signer *types.OV queueOrigin, &res.Transaction.Index, res.Transaction.QueueIndex, - nil, // TODO: UPDATE THIS + res.Transaction.Data, ) tx.SetTransactionMeta(txMeta) @@ -312,7 +312,7 @@ func transactionResponseToTransaction(res *TransactionResponse, signer *types.OV queueOrigin, &res.Transaction.Index, res.Transaction.QueueIndex, - nil, // TODO: UPDATE THIS + res.Transaction.Data, ) tx.SetTransactionMeta(txMeta) return tx, nil From b5a87452dafc4967e4a38df61707bbde6a83e160 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Fri, 5 Mar 2021 22:46:24 -0800 Subject: [PATCH 03/10] Remove encoding from to OVM message --- core/state_transition_ovm.go | 58 +----------------------------------- 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/core/state_transition_ovm.go b/core/state_transition_ovm.go index 1fd43c23e..991c7048c 100644 --- a/core/state_transition_ovm.go +++ b/core/state_transition_ovm.go @@ -1,7 +1,6 @@ package core import ( - "bytes" "fmt" "math/big" @@ -79,56 +78,13 @@ func AsOvmMessage(tx *types.Transaction, signer types.Signer, decompressor commo return msg, nil } - v, r, s := tx.RawSignatureValues() - - // V parameter here will include the chain ID, so we need to recover the original V. If the V - // does not equal zero or one, we have an invalid parameter and need to throw an error. - // This is technically a duplicate check because it happens inside of - // `tx.AsMessage` as well. - v = new(big.Int).SetUint64(v.Uint64() - 35 - 2*tx.ChainId().Uint64()) - if v.Uint64() != 0 && v.Uint64() != 1 { - index := tx.GetMeta().Index - if index == nil { - return msg, fmt.Errorf("invalid signature v parameter: %d", v.Uint64()) - } - } - - // Since we use a fixed encoding, we need to insert some placeholder address to represent that - // the user wants to create a contract (in this case, the zero address). - var target common.Address - if tx.To() == nil { - target = ZeroAddress - } else { - target = *tx.To() - } - - // Divide the gas price by one million to compress it - // before it is send to the sequencer entrypoint. This is to save - // space on calldata. - gasPrice := new(big.Int).Div(msg.GasPrice(), new(big.Int).SetUint64(1000000)) - - // Sequencer uses a custom encoding structure -- - // We originally receive sequencer transactions encoded in this way, but we decode them before - // inserting into Geth so we can make transactions easily parseable. However, this means that - // we need to re-encode the transactions before executing them. - var data = new(bytes.Buffer) - data.WriteByte(getSignatureType(msg)) // 1 byte: 00 == EIP 155, 02 == ETH Sign Message - data.Write(fillBytes(r, 32)) // 32 bytes: Signature `r` parameter - data.Write(fillBytes(s, 32)) // 32 bytes: Signature `s` parameter - data.Write(fillBytes(v, 1)) // 1 byte: Signature `v` parameter - data.Write(fillBytes(big.NewInt(int64(msg.Gas())), 3)) // 3 bytes: Gas limit - data.Write(fillBytes(gasPrice, 3)) // 3 bytes: Gas price - data.Write(fillBytes(big.NewInt(int64(msg.Nonce())), 3)) // 3 bytes: Nonce - data.Write(target.Bytes()) // 20 bytes: Target address - data.Write(msg.Data()) // ?? bytes: Transaction data - // Sequencer transactions get sent to the "sequencer entrypoint," a contract that decompresses // the incoming transaction data. outmsg, err := modMessage( msg, msg.From(), &decompressor, - data.Bytes(), + tx.GetMeta().RawTransaction, msg.Gas(), ) @@ -201,18 +157,6 @@ func modMessage( return outmsg, nil } -func getSignatureType( - msg Message, -) uint8 { - if msg.SignatureHashType() == 0 { - return 0 - } else if msg.SignatureHashType() == 1 { - return 2 - } else { - return 1 - } -} - func getQueueOrigin( queueOrigin *big.Int, ) (types.QueueOrigin, error) { From f2bffa4ef7379c00c0ab5c858e7b4358fa0f448e Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Fri, 5 Mar 2021 23:45:07 -0800 Subject: [PATCH 04/10] Correctly encode apply transaction --- rollup/sync_service.go | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/rollup/sync_service.go b/rollup/sync_service.go index 2214ef8ad..94f64e15c 100644 --- a/rollup/sync_service.go +++ b/rollup/sync_service.go @@ -1,6 +1,7 @@ package rollup import ( + "bytes" "context" "errors" "fmt" @@ -10,6 +11,7 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" @@ -640,5 +642,80 @@ func (s *SyncService) ApplyTransaction(tx *types.Transaction) error { if err != nil { return fmt.Errorf("invalid transaction: %w", err) } + + // Set the raw transaction data in the meta + txRaw := getRawTransaction(*tx) + meta := tx.GetMeta() + newMeta := types.NewTransactionMeta( + meta.L1BlockNumber, + meta.L1Timestamp, + meta.L1MessageSender, + meta.SignatureHashType, + types.QueueOrigin(meta.QueueOrigin.Uint64()), + meta.Index, + meta.QueueIndex, + txRaw, + ) + tx.SetTransactionMeta(newMeta) + return s.applyTransaction(tx) } + +func getRawTransaction(tx types.Transaction) []byte { + v, r, s := tx.RawSignatureValues() + + // Since we use a fixed encoding, we need to insert some placeholder address to represent that + // the user wants to create a contract (in this case, the zero address). + var target common.Address + if tx.To() == nil { + target = common.HexToAddress("0x0000000000000000000000000000000000000000") + } else { + target = *tx.To() + } + + // Divide the gas price by one million to compress it + // before it is send to the sequencer entrypoint. This is to save + // space on calldata. + gasPrice := new(big.Int).Div(tx.GasPrice(), new(big.Int).SetUint64(1000000)) + + // Sequencer uses a custom encoding structure -- + // We originally receive sequencer transactions encoded in this way, but we decode them before + // inserting into Geth so we can make transactions easily parseable. However, this means that + // we need to re-encode the transactions before executing them. + var data = new(bytes.Buffer) + data.WriteByte(getSignatureType(tx)) // 1 byte: 00 == EIP 155, 02 == ETH Sign Message + data.Write(fillBytes(r, 32)) // 32 bytes: Signature `r` parameter + data.Write(fillBytes(s, 32)) // 32 bytes: Signature `s` parameter + data.Write(fillBytes(v, 1)) // 1 byte: Signature `v` parameter + data.Write(fillBytes(big.NewInt(int64(tx.Gas())), 3)) // 3 bytes: Gas limit + data.Write(fillBytes(gasPrice, 3)) // 3 bytes: Gas price + data.Write(fillBytes(big.NewInt(int64(tx.Nonce())), 3)) // 3 bytes: Nonce + data.Write(target.Bytes()) // 20 bytes: Target address + data.Write(tx.Data()) + + return data.Bytes() +} + +func fillBytes(x *big.Int, size int) []byte { + b := x.Bytes() + switch { + case len(b) > size: + panic("math/big: value won't fit requested size") + case len(b) == size: + return b + default: + buf := make([]byte, size) + copy(buf[size-len(b):], b) + return buf + } +} + +func getSignatureType(tx types.Transaction) uint8 { + if tx.SignatureHashType() == 0 { + return 0 + } else if tx.SignatureHashType() == 1 { + return 2 + } else { + return 1 + } +} From 07a13982a4983fc0cc80d0e77b66a518de4e75b3 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Sat, 6 Mar 2021 17:22:30 -0800 Subject: [PATCH 05/10] Transform v to 1 byte --- rollup/sync_service.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/rollup/sync_service.go b/rollup/sync_service.go index 94f64e15c..ff29145b7 100644 --- a/rollup/sync_service.go +++ b/rollup/sync_service.go @@ -644,7 +644,10 @@ func (s *SyncService) ApplyTransaction(tx *types.Transaction) error { } // Set the raw transaction data in the meta - txRaw := getRawTransaction(*tx) + txRaw, err := getRawTransaction(*tx) + if err != nil { + return fmt.Errorf("invalid transaction: %w", err) + } meta := tx.GetMeta() newMeta := types.NewTransactionMeta( meta.L1BlockNumber, @@ -661,9 +664,18 @@ func (s *SyncService) ApplyTransaction(tx *types.Transaction) error { return s.applyTransaction(tx) } -func getRawTransaction(tx types.Transaction) []byte { +func getRawTransaction(tx types.Transaction) ([]byte, error) { v, r, s := tx.RawSignatureValues() + // V parameter here will include the chain ID, so we need to recover the original V. If the V + // does not equal zero or one, we have an invalid parameter and need to throw an error. + // This is technically a duplicate check because it happens inside of + // `tx.AsMessage` as well. + v = new(big.Int).SetUint64(v.Uint64() - 35 - 2*tx.ChainId().Uint64()) + if v.Uint64() != 0 && v.Uint64() != 1 { + return nil, fmt.Errorf("invalid signature v parameter: %d", v.Uint64()) + } + // Since we use a fixed encoding, we need to insert some placeholder address to represent that // the user wants to create a contract (in this case, the zero address). var target common.Address @@ -693,7 +705,7 @@ func getRawTransaction(tx types.Transaction) []byte { data.Write(target.Bytes()) // 20 bytes: Target address data.Write(tx.Data()) - return data.Bytes() + return data.Bytes(), nil } func fillBytes(x *big.Int, size int) []byte { From c1c8d822df2a707fdd47024e8733cd8a175eb7f3 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Sat, 6 Mar 2021 17:34:02 -0800 Subject: [PATCH 06/10] Fix lint err --- core/state_transition_ovm.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/core/state_transition_ovm.go b/core/state_transition_ovm.go index 991c7048c..9b504a620 100644 --- a/core/state_transition_ovm.go +++ b/core/state_transition_ovm.go @@ -170,17 +170,3 @@ func getQueueOrigin( return types.QueueOriginSequencer, fmt.Errorf("invalid queue origin: %d", queueOrigin) } } - -func fillBytes(x *big.Int, size int) []byte { - b := x.Bytes() - switch { - case len(b) > size: - panic("math/big: value won't fit requested size") - case len(b) == size: - return b - default: - buf := make([]byte, size) - copy(buf[size-len(b):], b) - return buf - } -} From a77b2f51f78f463a1311f0b692132613c8e041e8 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Sun, 7 Mar 2021 17:19:16 -0800 Subject: [PATCH 07/10] rpc: add rawTransaction --- internal/ethapi/api.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 231b6b4e6..6da198359 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1177,6 +1177,7 @@ type RPCTransaction struct { L1Timestamp hexutil.Uint64 `json:"l1Timestamp"` Index *hexutil.Uint64 `json:"index"` QueueIndex *hexutil.Uint64 `json:"queueIndex"` + RawTransaction hexutil.Bytes `json:"rawTransaction"` } // newRPCTransaction returns a transaction that will serialize to the RPC @@ -1210,6 +1211,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber } if meta := tx.GetMeta(); meta != nil { + result.RawTransaction = meta.RawTransaction result.L1TxOrigin = meta.L1MessageSender result.L1Timestamp = (hexutil.Uint64)(meta.L1Timestamp) if meta.L1BlockNumber != nil { From ffeee6b593038a1a85292d1866c5b1148430a617 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Mon, 8 Mar 2021 10:30:50 -0800 Subject: [PATCH 08/10] syncservice: clean up serialization --- rollup/sync_service.go | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/rollup/sync_service.go b/rollup/sync_service.go index ff29145b7..8bea8c531 100644 --- a/rollup/sync_service.go +++ b/rollup/sync_service.go @@ -644,7 +644,7 @@ func (s *SyncService) ApplyTransaction(tx *types.Transaction) error { } // Set the raw transaction data in the meta - txRaw, err := getRawTransaction(*tx) + txRaw, err := getRawTransaction(tx) if err != nil { return fmt.Errorf("invalid transaction: %w", err) } @@ -664,7 +664,10 @@ func (s *SyncService) ApplyTransaction(tx *types.Transaction) error { return s.applyTransaction(tx) } -func getRawTransaction(tx types.Transaction) ([]byte, error) { +func getRawTransaction(tx *types.Transaction) ([]byte, error) { + if tx == nil { + return nil, errors.New("Cannot process nil transaction") + } v, r, s := tx.RawSignatureValues() // V parameter here will include the chain ID, so we need to recover the original V. If the V @@ -680,7 +683,7 @@ func getRawTransaction(tx types.Transaction) ([]byte, error) { // the user wants to create a contract (in this case, the zero address). var target common.Address if tx.To() == nil { - target = common.HexToAddress("0x0000000000000000000000000000000000000000") + target = common.Address{} } else { target = *tx.To() } @@ -695,14 +698,14 @@ func getRawTransaction(tx types.Transaction) ([]byte, error) { // inserting into Geth so we can make transactions easily parseable. However, this means that // we need to re-encode the transactions before executing them. var data = new(bytes.Buffer) - data.WriteByte(getSignatureType(tx)) // 1 byte: 00 == EIP 155, 02 == ETH Sign Message - data.Write(fillBytes(r, 32)) // 32 bytes: Signature `r` parameter - data.Write(fillBytes(s, 32)) // 32 bytes: Signature `s` parameter - data.Write(fillBytes(v, 1)) // 1 byte: Signature `v` parameter - data.Write(fillBytes(big.NewInt(int64(tx.Gas())), 3)) // 3 bytes: Gas limit - data.Write(fillBytes(gasPrice, 3)) // 3 bytes: Gas price - data.Write(fillBytes(big.NewInt(int64(tx.Nonce())), 3)) // 3 bytes: Nonce - data.Write(target.Bytes()) // 20 bytes: Target address + data.WriteByte(getSignatureType(tx)) // 1 byte: 00 == EIP 155, 02 == ETH Sign Message + data.Write(fillBytes(r, 32)) // 32 bytes: Signature `r` parameter + data.Write(fillBytes(s, 32)) // 32 bytes: Signature `s` parameter + data.Write(fillBytes(v, 1)) // 1 byte: Signature `v` parameter + data.Write(fillBytes(new(big.Int).SetUint64(tx.Gas()), 3)) // 3 bytes: Gas limit + data.Write(fillBytes(gasPrice, 3)) // 3 bytes: Gas price + data.Write(fillBytes(new(big.Int).SetUint64(tx.Nonce()), 3)) // 3 bytes: Nonce + data.Write(target.Bytes()) // 20 bytes: Target address data.Write(tx.Data()) return data.Bytes(), nil @@ -722,7 +725,7 @@ func fillBytes(x *big.Int, size int) []byte { } } -func getSignatureType(tx types.Transaction) uint8 { +func getSignatureType(tx *types.Transaction) uint8 { if tx.SignatureHashType() == 0 { return 0 } else if tx.SignatureHashType() == 1 { From 3319556152f1575ba7ff103781b634cd13768fb5 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Mon, 8 Mar 2021 21:45:59 -0800 Subject: [PATCH 09/10] enums: temp fix --- rollup/sync_service.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rollup/sync_service.go b/rollup/sync_service.go index 8bea8c531..4ec1d3efa 100644 --- a/rollup/sync_service.go +++ b/rollup/sync_service.go @@ -616,6 +616,7 @@ func (s *SyncService) maybeApplyTransaction(tx *types.Transaction) error { // Lower level API used to apply a transaction, must only be used with // transactions that came from L1. func (s *SyncService) applyTransaction(tx *types.Transaction) error { + tx = fixType(tx) txs := types.Transactions{tx} s.txFeed.Send(core.NewTxsEvent{Txs: txs}) return nil @@ -734,3 +735,18 @@ func getSignatureType(tx *types.Transaction) uint8 { return 1 } } + +// This is a temporary fix to patch the enums being used in the raw data +func fixType(tx *types.Transaction) *types.Transaction { + meta := tx.GetMeta() + raw := meta.RawTransaction + if raw[0] == 0x00 { + return tx + } else if raw[0] == 0x01 { + raw[0] = 0x02 + } + queueOrigin := types.QueueOrigin(meta.QueueOrigin.Uint64()) + fixed := types.NewTransactionMeta(meta.L1BlockNumber, meta.L1Timestamp, meta.L1MessageSender, meta.SignatureHashType, queueOrigin, meta.Index, meta.QueueIndex, raw) + tx.SetTransactionMeta(fixed) + return tx +} From f2114cbb2df5842bc3f8d0f81743ce5c4e077675 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Mon, 8 Mar 2021 22:03:18 -0800 Subject: [PATCH 10/10] enums: safety --- rollup/sync_service.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rollup/sync_service.go b/rollup/sync_service.go index 4ec1d3efa..5f9f99f5d 100644 --- a/rollup/sync_service.go +++ b/rollup/sync_service.go @@ -740,6 +740,10 @@ func getSignatureType(tx *types.Transaction) uint8 { func fixType(tx *types.Transaction) *types.Transaction { meta := tx.GetMeta() raw := meta.RawTransaction + if len(raw) == 0 { + log.Error("Transaction with no raw detected") + return tx + } if raw[0] == 0x00 { return tx } else if raw[0] == 0x01 {