eth-sign like signature hash (#15)

* eth-sign: initial implementation

* sighash: pre-refactor

* sighash: refactor, all old tests pass

* sighash: test ovmsigner code paths for eip155 and eth_sign

* sighash: tx serialization tests

* sighash: refactor to sign bytes

* common/varbytes: use varbytes serialization from btcd

* transactionmeta: implement and test

* rawdb: add new index

* types/transaction: use txmeta

* blockchain: index tx meta on new block

* rpc: fix sendrawethsigntransaction docstring

* meta test: remove dead code

* ethapi: clean up comment

* lint: fix

* txmeta: clean up compares

* ethapi: remove rlp tag

* signer: remove rlp encoding tags from struct

* types: use factory pattern for getting sighash type

* sighash: migrate to using const

* tx pool: use ovmsigner for tx validation

* tx signing: fix eth_sign serialization

* sighash: new version

* sighash: commit to chainid

* sighash: bugfixes

* core/types: prevent panic on tx sort

* core/types: rename to transaction_meta

* core/blockchain: index txmeta

* sighash: no native value

* ethapi: use ovm signer

* sighash: move chainid
This commit is contained in:
Mark Tyneway 2020-09-13 11:15:42 -07:00 committed by GitHub
parent 538ddf8fc0
commit 680b4f874b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1268 additions and 302 deletions

View File

@ -246,7 +246,7 @@ func TestSimulatedBackend_NonceAt(t *testing.T) {
}
// create a signed transaction to send
tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
@ -281,7 +281,7 @@ func TestSimulatedBackend_SendTransaction(t *testing.T) {
bgCtx := context.Background()
// create a signed transaction to send
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
@ -316,7 +316,7 @@ func TestSimulatedBackend_TransactionByHash(t *testing.T) {
bgCtx := context.Background()
// create a signed transaction to send
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
@ -481,7 +481,7 @@ func TestSimulatedBackend_TransactionCount(t *testing.T) {
}
// create a signed transaction to send
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
@ -540,7 +540,7 @@ func TestSimulatedBackend_TransactionInBlock(t *testing.T) {
}
// create a signed transaction to send
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
@ -599,7 +599,7 @@ func TestSimulatedBackend_PendingNonceAt(t *testing.T) {
}
// create a signed transaction to send
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
@ -622,7 +622,7 @@ func TestSimulatedBackend_PendingNonceAt(t *testing.T) {
}
// make a new transaction with a nonce of 1
tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
@ -655,7 +655,7 @@ func TestSimulatedBackend_TransactionReceipt(t *testing.T) {
bgCtx := context.Background()
// create a signed transaction to send
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil)
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)

View File

@ -229,7 +229,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if contract == nil {
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input, nil, nil)
} else {
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input, nil, nil)
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input, nil, nil, types.SighashEIP155)
}
if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with")

View File

@ -490,7 +490,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil))
amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil))
tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil, nil, nil)
tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil, nil, nil, types.SighashEIP155)
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainID)
if err != nil {
f.lock.Unlock()

383
common/varbytes.go Normal file
View File

@ -0,0 +1,383 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package common
import (
"encoding/binary"
"fmt"
"io"
"math"
)
const (
// MaxVarIntPayload is the maximum payload size for a variable length integer.
MaxVarIntPayload = 9
// binaryFreeListMaxItems is the number of buffers to keep in the free
// list to use for binary serialization and deserialization.
binaryFreeListMaxItems = 1024
)
var (
// littleEndian is a convenience variable since binary.LittleEndian is
// quite long.
littleEndian = binary.LittleEndian
)
// binaryFreeList defines a concurrent safe free list of byte slices (up to the
// maximum number defined by the binaryFreeListMaxItems constant) that have a
// cap of 8 (thus it supports up to a uint64). It is used to provide temporary
// buffers for serializing and deserializing primitive numbers to and from their
// binary encoding in order to greatly reduce the number of allocations
// required.
//
// For convenience, functions are provided for each of the primitive unsigned
// integers that automatically obtain a buffer from the free list, perform the
// necessary binary conversion, read from or write to the given io.Reader or
// io.Writer, and return the buffer to the free list.
type binaryFreeList chan []byte
// Borrow returns a byte slice from the free list with a length of 8. A new
// buffer is allocated if there are not any available on the free list.
func (l binaryFreeList) Borrow() []byte {
var buf []byte
select {
case buf = <-l:
default:
buf = make([]byte, 8)
}
return buf[:8]
}
// Return puts the provided byte slice back on the free list. The buffer MUST
// have been obtained via the Borrow function and therefore have a cap of 8.
func (l binaryFreeList) Return(buf []byte) {
select {
case l <- buf:
default:
// Let it go to the garbage collector.
}
}
// Uint8 reads a single byte from the provided reader using a buffer from the
// free list and returns it as a uint8.
func (l binaryFreeList) Uint8(r io.Reader) (uint8, error) {
buf := l.Borrow()[:1]
if _, err := io.ReadFull(r, buf); err != nil {
l.Return(buf)
return 0, err
}
rv := buf[0]
l.Return(buf)
return rv, nil
}
// Uint16 reads two bytes from the provided reader using a buffer from the
// free list, converts it to a number using the provided byte order, and returns
// the resulting uint16.
func (l binaryFreeList) Uint16(r io.Reader, byteOrder binary.ByteOrder) (uint16, error) {
buf := l.Borrow()[:2]
if _, err := io.ReadFull(r, buf); err != nil {
l.Return(buf)
return 0, err
}
rv := byteOrder.Uint16(buf)
l.Return(buf)
return rv, nil
}
// Uint32 reads four bytes from the provided reader using a buffer from the
// free list, converts it to a number using the provided byte order, and returns
// the resulting uint32.
func (l binaryFreeList) Uint32(r io.Reader, byteOrder binary.ByteOrder) (uint32, error) {
buf := l.Borrow()[:4]
if _, err := io.ReadFull(r, buf); err != nil {
l.Return(buf)
return 0, err
}
rv := byteOrder.Uint32(buf)
l.Return(buf)
return rv, nil
}
// Uint64 reads eight bytes from the provided reader using a buffer from the
// free list, converts it to a number using the provided byte order, and returns
// the resulting uint64.
func (l binaryFreeList) Uint64(r io.Reader, byteOrder binary.ByteOrder) (uint64, error) {
buf := l.Borrow()[:8]
if _, err := io.ReadFull(r, buf); err != nil {
l.Return(buf)
return 0, err
}
rv := byteOrder.Uint64(buf)
l.Return(buf)
return rv, nil
}
// PutUint8 copies the provided uint8 into a buffer from the free list and
// writes the resulting byte to the given writer.
func (l binaryFreeList) PutUint8(w io.Writer, val uint8) error {
buf := l.Borrow()[:1]
buf[0] = val
_, err := w.Write(buf)
l.Return(buf)
return err
}
// PutUint16 serializes the provided uint16 using the given byte order into a
// buffer from the free list and writes the resulting two bytes to the given
// writer.
func (l binaryFreeList) PutUint16(w io.Writer, byteOrder binary.ByteOrder, val uint16) error {
buf := l.Borrow()[:2]
byteOrder.PutUint16(buf, val)
_, err := w.Write(buf)
l.Return(buf)
return err
}
// PutUint32 serializes the provided uint32 using the given byte order into a
// buffer from the free list and writes the resulting four bytes to the given
// writer.
func (l binaryFreeList) PutUint32(w io.Writer, byteOrder binary.ByteOrder, val uint32) error {
buf := l.Borrow()[:4]
byteOrder.PutUint32(buf, val)
_, err := w.Write(buf)
l.Return(buf)
return err
}
// PutUint64 serializes the provided uint64 using the given byte order into a
// buffer from the free list and writes the resulting eight bytes to the given
// writer.
func (l binaryFreeList) PutUint64(w io.Writer, byteOrder binary.ByteOrder, val uint64) error {
buf := l.Borrow()[:8]
byteOrder.PutUint64(buf, val)
_, err := w.Write(buf)
l.Return(buf)
return err
}
// binarySerializer provides a free list of buffers to use for serializing and
// deserializing primitive integer values to and from io.Readers and io.Writers.
var binarySerializer binaryFreeList = make(chan []byte, binaryFreeListMaxItems)
// errNonCanonicalVarInt is the common format string used for non-canonically
// encoded variable length integer errors.
var errNonCanonicalVarInt = "non-canonical varint %x - discriminant %x must " +
"encode a value greater than %x"
// ReadVarInt reads a variable length integer from r and returns it as a uint64.
func ReadVarInt(r io.Reader, pver uint32) (uint64, error) {
discriminant, err := binarySerializer.Uint8(r)
if err != nil {
return 0, err
}
var rv uint64
switch discriminant {
case 0xff:
sv, err := binarySerializer.Uint64(r, littleEndian)
if err != nil {
return 0, err
}
rv = sv
// The encoding is not canonical if the value could have been
// encoded using fewer bytes.
min := uint64(0x100000000)
if rv < min {
return 0, messageError("ReadVarInt", fmt.Sprintf(
errNonCanonicalVarInt, rv, discriminant, min))
}
case 0xfe:
sv, err := binarySerializer.Uint32(r, littleEndian)
if err != nil {
return 0, err
}
rv = uint64(sv)
// The encoding is not canonical if the value could have been
// encoded using fewer bytes.
min := uint64(0x10000)
if rv < min {
return 0, messageError("ReadVarInt", fmt.Sprintf(
errNonCanonicalVarInt, rv, discriminant, min))
}
case 0xfd:
sv, err := binarySerializer.Uint16(r, littleEndian)
if err != nil {
return 0, err
}
rv = uint64(sv)
// The encoding is not canonical if the value could have been
// encoded using fewer bytes.
min := uint64(0xfd)
if rv < min {
return 0, messageError("ReadVarInt", fmt.Sprintf(
errNonCanonicalVarInt, rv, discriminant, min))
}
default:
rv = uint64(discriminant)
}
return rv, nil
}
// WriteVarInt serializes val to w using a variable number of bytes depending
// on its value.
func WriteVarInt(w io.Writer, pver uint32, val uint64) error {
if val < 0xfd {
return binarySerializer.PutUint8(w, uint8(val))
}
if val <= math.MaxUint16 {
err := binarySerializer.PutUint8(w, 0xfd)
if err != nil {
return err
}
return binarySerializer.PutUint16(w, littleEndian, uint16(val))
}
if val <= math.MaxUint32 {
err := binarySerializer.PutUint8(w, 0xfe)
if err != nil {
return err
}
return binarySerializer.PutUint32(w, littleEndian, uint32(val))
}
err := binarySerializer.PutUint8(w, 0xff)
if err != nil {
return err
}
return binarySerializer.PutUint64(w, littleEndian, val)
}
// VarIntSerializeSize returns the number of bytes it would take to serialize
// val as a variable length integer.
func VarIntSerializeSize(val uint64) int {
// The value is small enough to be represented by itself, so it's
// just 1 byte.
if val < 0xfd {
return 1
}
// Discriminant 1 byte plus 2 bytes for the uint16.
if val <= math.MaxUint16 {
return 3
}
// Discriminant 1 byte plus 4 bytes for the uint32.
if val <= math.MaxUint32 {
return 5
}
// Discriminant 1 byte plus 8 bytes for the uint64.
return 9
}
// ReadVarString reads a variable length string from r and returns it as a Go
// string. A variable length string is encoded as a variable length integer
// containing the length of the string followed by the bytes that represent the
// string itself.
func ReadVarString(r io.Reader, pver uint32) (string, error) {
count, err := ReadVarInt(r, pver)
if err != nil {
return "", err
}
buf := make([]byte, count)
_, err = io.ReadFull(r, buf)
if err != nil {
return "", err
}
return string(buf), nil
}
// WriteVarString serializes str to w as a variable length integer containing
// the length of the string followed by the bytes that represent the string
// itself.
func WriteVarString(w io.Writer, pver uint32, str string) error {
err := WriteVarInt(w, pver, uint64(len(str)))
if err != nil {
return err
}
_, err = w.Write([]byte(str))
return err
}
// ReadVarBytes reads a variable length byte array. A byte array is encoded
// as a varInt containing the length of the array followed by the bytes
// themselves. An error is returned if the length is greater than the
// passed maxAllowed parameter which helps protect against memory exhaustion
// attacks and forced panics through malformed messages. The fieldName
// parameter is only used for the error message so it provides more context in
// the error.
func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32,
fieldName string) ([]byte, error) {
count, err := ReadVarInt(r, pver)
if err != nil {
return nil, err
}
// Prevent byte array larger than the max message size. It would
// be possible to cause memory exhaustion and panics without a sane
// upper bound on this count.
if count > uint64(maxAllowed) {
str := fmt.Sprintf("%s is larger than the max allowed size "+
"[count %d, max %d]", fieldName, count, maxAllowed)
return nil, messageError("ReadVarBytes", str)
}
b := make([]byte, count)
_, err = io.ReadFull(r, b)
if err != nil {
return nil, err
}
return b, nil
}
// WriteVarBytes serializes a variable length byte array to w as a varInt
// containing the number of bytes, followed by the bytes themselves.
func WriteVarBytes(w io.Writer, pver uint32, bytes []byte) error {
slen := uint64(len(bytes))
err := WriteVarInt(w, pver, slen)
if err != nil {
return err
}
_, err = w.Write(bytes)
return err
}
// MessageError describes an issue with a message.
// An example of some potential issues are messages from the wrong bitcoin
// network, invalid commands, mismatched checksums, and exceeding max payloads.
//
// This provides a mechanism for the caller to type assert the error to
// differentiate between general io errors such as io.EOF and issues that
// resulted from malformed messages.
type MessageError struct {
Func string // Function name
Description string // Human readable description of the issue
}
// Error satisfies the error interface and prints human-readable errors.
func (e *MessageError) Error() string {
if e.Func != "" {
return fmt.Sprintf("%v: %v", e.Func, e.Description)
}
return e.Description
}
// messageError creates an error for the given function and description.
func messageError(f string, desc string) *MessageError {
return &MessageError{Func: f, Description: desc}
}

View File

@ -65,7 +65,7 @@ func TestReimportMirroredState(t *testing.T) {
// We want to simulate an empty middle block, having the same state as the
// first one. The last is needs a state change again to force a reorg.
if i != 1 {
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr), common.Address{0x00}, new(big.Int), params.TxGas, nil, nil, nil, nil), signer, key)
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr), common.Address{0x00}, new(big.Int), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key)
if err != nil {
panic(err)
}

View File

@ -86,7 +86,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
gas, _ := IntrinsicGas(data, false, false, false)
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data, nil, nil), types.HomesteadSigner{}, benchRootKey)
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, benchRootKey)
gen.AddTx(tx)
}
}
@ -119,7 +119,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
break
}
to := (from + 1) % naccounts
tx := types.NewTransaction(gen.TxNonce(ringAddrs[from]), ringAddrs[to], benchRootFunds, params.TxGas, nil, nil, nil, nil)
tx := types.NewTransaction(gen.TxNonce(ringAddrs[from]), ringAddrs[to], benchRootFunds, params.TxGas, nil, nil, nil, nil, types.SighashEIP155)
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, ringKeys[from])
gen.AddTx(tx)
from = to

View File

@ -1221,6 +1221,9 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
rawdb.WriteTxLookupEntries(batch, block)
for _, tx := range block.Transactions() {
rawdb.WriteTransactionMeta(batch, tx.Hash(), tx.GetMeta())
}
// Write everything belongs to the blocks into the database. So that
// we can ensure all components of body is completed(body, receipts,
@ -1343,6 +1346,9 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
blockBatch := bc.db.NewBatch()
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
rawdb.WriteBlock(blockBatch, block)
for _, tx := range block.Transactions() {
rawdb.WriteTransactionMeta(blockBatch, tx.Hash(), tx.GetMeta())
}
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
rawdb.WritePreimages(blockBatch, state.Preimages())
if err := blockBatch.Write(); err != nil {

View File

@ -607,7 +607,7 @@ func TestFastVsFullChains(t *testing.T) {
// If the block number is multiple of 3, send a few bonus transactions to the miner
if i%3 == 2 {
for j := 0; j < i%4+1; j++ {
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key)
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key)
if err != nil {
panic(err)
}
@ -840,8 +840,8 @@ func TestChainTxReorgs(t *testing.T) {
// Create two transactions shared between the chains:
// - postponed: transaction included at a later block in the forked chain
// - swapped: transaction included at the same block number in the forked chain
postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key1)
swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key1)
postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key1)
swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key1)
// Create two transactions that will be dropped by the forked chain:
// - pastDrop: transaction dropped retroactively from a past block
@ -857,13 +857,13 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {
switch i {
case 0:
pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key2)
pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key2)
gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
case 2:
freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key2)
freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key2)
gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
gen.AddTx(swapped) // This transaction will be swapped out at the exact height
@ -882,18 +882,18 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key3)
pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key3)
gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
case 2:
gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key3)
freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key3)
gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
case 3:
futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, key3)
futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, key3)
gen.AddTx(futureAdd) // This transaction will be added after a full reorg
}
})
@ -1340,7 +1340,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil, nil, nil), signer, key)
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil, nil, nil, types.SighashEIP155), signer, key)
}
)
switch i {
@ -1403,7 +1403,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil, nil, nil), signer, key)
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil, nil, nil, types.SighashEIP155), signer, key)
}
)
if i == 0 {
@ -1453,11 +1453,11 @@ func TestEIP161AccountRemoval(t *testing.T) {
)
switch i {
case 0:
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil, nil, nil), signer, key)
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil, nil, nil, types.SighashEIP155), signer, key)
case 1:
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil, nil, nil), signer, key)
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil, nil, nil, types.SighashEIP155), signer, key)
case 2:
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil, nil, nil), signer, key)
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil, nil, nil, types.SighashEIP155), signer, key)
}
if err != nil {
t.Fatal(err)
@ -2166,7 +2166,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
for txi := 0; txi < numTxs; txi++ {
uniq := uint64(i*numTxs + txi)
recipient := recipientFn(uniq)
tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil, nil, nil), signer, testBankKey)
tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil, nil, nil, types.SighashEIP155), signer, testBankKey)
if err != nil {
b.Error(err)
}
@ -2346,10 +2346,10 @@ func TestDeleteCreateRevert(t *testing.T) {
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{1})
// One transaction to AAAA
tx, _ := types.SignTx(types.NewTransaction(0, aa, big.NewInt(0), 50000, big.NewInt(1), nil, nil, nil), types.HomesteadSigner{}, key)
tx, _ := types.SignTx(types.NewTransaction(0, aa, big.NewInt(0), 50000, big.NewInt(1), nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, key)
b.AddTx(tx)
// One transaction to BBBB
tx, _ = types.SignTx(types.NewTransaction(1, bb, big.NewInt(0), 100000, big.NewInt(1), nil, nil, nil), types.HomesteadSigner{}, key)
tx, _ = types.SignTx(types.NewTransaction(1, bb, big.NewInt(0), 100000, big.NewInt(1), nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, key)
b.AddTx(tx)
})
// Import the canonical chain

View File

@ -338,6 +338,53 @@ func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
}
}
// ReadTransactionMeta returns the transaction metadata associated with a
// transaction hash.
func ReadTransactionMeta(db ethdb.Reader, hash common.Hash) *types.TransactionMeta {
data := ReadTransactionMetaRaw(db, hash)
if len(data) == 0 {
return nil
}
meta, err := types.TxMetaDecode(data)
if err != nil {
log.Error("Invalid raw tx meta ", "hash", hash, "err", err)
return nil
}
return meta
}
// ReadTransactionMetaRaw returns the raw transaction metadata associated with a
// transaction hash.
func ReadTransactionMetaRaw(db ethdb.Reader, hash common.Hash) []byte {
data, _ := db.Get(txMetaKey(hash))
if len(data) > 0 {
return data
}
return nil
}
// WriteTransactionMeta writes the TransactionMeta to disk by hash.
func WriteTransactionMeta(db ethdb.KeyValueWriter, hash common.Hash, meta *types.TransactionMeta) {
data := types.TxMetaEncode(meta)
WriteTransactionMetaRaw(db, hash, data)
}
// WriteTransactionMetaRaw writes the raw transaction metadata bytes to disk.
func WriteTransactionMetaRaw(db ethdb.KeyValueWriter, hash common.Hash, data []byte) {
if err := db.Put(txMetaKey(hash), data); err != nil {
log.Crit("Failed to store transaction meta", "err", err)
}
}
// DeleteTransactionMeta removes the transaction metadata associated with a hash
func DeleteTransactionMeta(db ethdb.KeyValueWriter, hash common.Hash) {
if err := db.Delete(txMetaKey(hash)); err != nil {
log.Crit("Failed to delete transaction meta", "err", err)
}
}
// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
// First try to look up the data in ancient database. Extra hash

View File

@ -26,6 +26,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
@ -273,8 +274,8 @@ func TestBlockReceiptStorage(t *testing.T) {
db := NewMemoryDatabase()
// Create a live block since we need metadata to reconstruct the receipt
tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil, nil, nil)
tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil, nil, nil)
tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil, nil, nil, types.SighashEIP155)
body := &types.Body{Transactions: types.Transactions{tx1, tx2}}
@ -424,3 +425,49 @@ func TestAncientStorage(t *testing.T) {
t.Fatalf("invalid td returned")
}
}
func TestBlockMetaStorage(t *testing.T) {
db := NewMemoryDatabase()
tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil, nil, nil, types.SighashEIP155)
WriteTransactionMeta(db, tx1.Hash(), tx1.GetMeta())
meta := ReadTransactionMeta(db, tx1.Hash())
if meta.L1MessageSender != nil {
t.Fatalf("Could not recover L1MessageSender")
}
if meta.L1RollupTxId != nil {
t.Fatalf("Could not recover L1RollupTxId")
}
if meta.SignatureHashType != types.SighashEIP155 {
t.Fatalf("Could not recover sighash type")
}
DeleteTransactionMeta(db, tx1.Hash())
postDelete := ReadTransactionMeta(db, tx1.Hash())
if postDelete != nil {
t.Fatalf("Delete did not work")
}
addr := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
txid := hexutil.Uint64(777)
tx2 := types.NewTransaction(2, common.HexToAddress("0x02"), big.NewInt(2), 2, big.NewInt(2), nil, &addr, &txid, types.SighashEthSign)
WriteTransactionMeta(db, tx2.Hash(), tx2.GetMeta())
meta2 := ReadTransactionMeta(db, tx2.Hash())
if !bytes.Equal(meta2.L1MessageSender.Bytes(), addr.Bytes()) {
t.Fatalf("Could not recover L1MessageSender")
}
if *meta2.L1RollupTxId != txid {
t.Fatalf("Could not recover L1RollupTxId")
}
if meta2.SignatureHashType != types.SighashEthSign {
t.Fatalf("Could not recover sighash type")
}
}

View File

@ -86,6 +86,11 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com
}
for txIndex, tx := range body.Transactions {
if tx.Hash() == hash {
txMeta := ReadTransactionMeta(db, hash)
if txMeta != nil {
tx.SetTransactionMeta(txMeta)
}
return tx, blockHash, *blockNumber, uint64(txIndex)
}
}

View File

@ -74,9 +74,9 @@ func TestLookupStorage(t *testing.T) {
l1RollupTxId1 := hexutil.Uint64(1)
l1RollupTxId2 := hexutil.Uint64(2)
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}, &sender1, &l1RollupTxId1)
tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}, &sender2, &l1RollupTxId2)
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}, nil, &l1RollupTxId1)
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}, &sender1, &l1RollupTxId1, types.SighashEIP155)
tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}, &sender2, &l1RollupTxId2, types.SighashEIP155)
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}, nil, &l1RollupTxId1, types.SighashEIP155)
txs := []*types.Transaction{tx1, tx2, tx3}
block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil)

View File

@ -53,6 +53,9 @@ var (
txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata
bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits
// Optmism specific
txMetaPrefix = []byte("x") // txMetaPrefix + hash -> transaction metadata
preimagePrefix = []byte("secure-key-") // preimagePrefix + hash -> preimage
configPrefix = []byte("ethereum-config-") // config prefix for the db
@ -145,6 +148,11 @@ func txLookupKey(hash common.Hash) []byte {
return append(txLookupPrefix, hash.Bytes()...)
}
// txMetaKey = txMetaPrefix + hash
func txMetaKey(hash common.Hash) []byte {
return append(txMetaPrefix, hash.Bytes()...)
}
// bloomBitsKey = bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash
func bloomBitsKey(bit uint, section uint64, hash common.Hash) []byte {
key := append(append(bloomBitsPrefix, make([]byte, 10)...), hash.Bytes()...)

View File

@ -271,7 +271,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
config: config,
chainconfig: chainconfig,
chain: chain,
signer: types.NewEIP155Signer(chainconfig.ChainID),
signer: types.NewOVMSigner(chainconfig.ChainID),
pending: make(map[common.Address]*txList),
queue: make(map[common.Address]*txList),
beats: make(map[common.Address]time.Time),

View File

@ -73,7 +73,7 @@ func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Tr
}
func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil, nil, nil), types.HomesteadSigner{}, key)
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, key)
return tx
}
@ -81,7 +81,7 @@ func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key
data := make([]byte, bytes)
rand.Read(data)
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data, nil, nil), types.HomesteadSigner{}, key)
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, key)
return tx
}
@ -329,7 +329,7 @@ func TestTransactionNegativeValue(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil, nil, nil), types.HomesteadSigner{}, key)
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, key)
from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1))
if err := pool.AddRemote(tx); err != ErrNegativeValue {
@ -383,9 +383,9 @@ func TestTransactionDoubleNonce(t *testing.T) {
resetState()
signer := types.HomesteadSigner{}
tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil, nil, nil), signer, key)
tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil, nil, nil), signer, key)
tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil, nil, nil), signer, key)
tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil, nil, nil, types.SighashEIP155), signer, key)
tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil, nil, nil, types.SighashEIP155), signer, key)
tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil, nil, nil, types.SighashEIP155), signer, key)
// Add the first two transaction, ensure higher priced stays only
if replace, err := pool.add(tx1, false); err != nil || replace {

View File

@ -50,7 +50,7 @@ func TestBlockEncoding(t *testing.T) {
check("Time", block.Time(), uint64(1426516743))
check("Size", block.Size(), common.StorageSize(len(blockEnc)))
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil, nil, nil)
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil, nil, nil, SighashEIP155)
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"))
check("len(Transactions)", len(block.Transactions()), 1)
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())

View File

@ -13,101 +13,111 @@ import (
var _ = (*txdataMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (t txdata) MarshalJSON() ([]byte, error) {
type txdata struct {
AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
GasLimit hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"`
Payload hexutil.Bytes `json:"input" gencodec:"required"`
V *hexutil.Big `json:"v" gencodec:"required"`
R *hexutil.Big `json:"r" gencodec:"required"`
S *hexutil.Big `json:"s" gencodec:"required"`
Hash *common.Hash `json:"hash" rlp:"-"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty" rlp:"nil,?"`
L1MessageSender *common.Address `json:"l1MessageSender,omitempty" rlp:"nil,?"`
// TransactionMarshalJSON marshals as JSON.
func TransactionMarshalJSON(t *Transaction) ([]byte, error) {
type txnjson struct {
AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
GasLimit hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"`
Payload hexutil.Bytes `json:"input" gencodec:"required"`
V *hexutil.Big `json:"v" gencodec:"required"`
R *hexutil.Big `json:"r" gencodec:"required"`
S *hexutil.Big `json:"s" gencodec:"required"`
Hash *common.Hash `json:"hash" rlp:"-"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty" rlp:"nil,?"`
L1MessageSender *common.Address `json:"l1MessageSender,omitempty" rlp:"nil,?"`
SignatureHashType SignatureHashType `json:"signatureHashType,omitempty" rlp:"nil,?"`
}
var enc txdata
enc.AccountNonce = hexutil.Uint64(t.AccountNonce)
enc.Price = (*hexutil.Big)(t.Price)
enc.GasLimit = hexutil.Uint64(t.GasLimit)
enc.Recipient = t.Recipient
enc.L1MessageSender = t.L1MessageSender
enc.L1RollupTxId = t.L1RollupTxId
enc.Amount = (*hexutil.Big)(t.Amount)
enc.Payload = t.Payload
enc.V = (*hexutil.Big)(t.V)
enc.R = (*hexutil.Big)(t.R)
enc.S = (*hexutil.Big)(t.S)
enc.Hash = t.Hash
var enc txnjson
enc.AccountNonce = hexutil.Uint64(t.data.AccountNonce)
enc.Price = (*hexutil.Big)(t.data.Price)
enc.GasLimit = hexutil.Uint64(t.data.GasLimit)
enc.Recipient = t.data.Recipient
enc.L1MessageSender = t.meta.L1MessageSender
enc.L1RollupTxId = t.meta.L1RollupTxId
enc.SignatureHashType = t.meta.SignatureHashType
enc.Amount = (*hexutil.Big)(t.data.Amount)
enc.Payload = t.data.Payload
enc.V = (*hexutil.Big)(t.data.V)
enc.R = (*hexutil.Big)(t.data.R)
enc.S = (*hexutil.Big)(t.data.S)
hash := t.Hash()
enc.Hash = &hash
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (t *txdata) UnmarshalJSON(input []byte) error {
type txdata struct {
AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"`
Payload *hexutil.Bytes `json:"input" gencodec:"required"`
V *hexutil.Big `json:"v" gencodec:"required"`
R *hexutil.Big `json:"r" gencodec:"required"`
S *hexutil.Big `json:"s" gencodec:"required"`
Hash *common.Hash `json:"hash" rlp:"-"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty" rlp:"nil,?"`
L1MessageSender *common.Address `json:"l1MessageSender,omitempty" rlp:"nil,?"`
func TransactionUnmarshalJSON(input []byte) (*Transaction, error) {
type txnjson struct {
AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"`
Payload *hexutil.Bytes `json:"input" gencodec:"required"`
V *hexutil.Big `json:"v" gencodec:"required"`
R *hexutil.Big `json:"r" gencodec:"required"`
S *hexutil.Big `json:"s" gencodec:"required"`
Hash *common.Hash `json:"hash" rlp:"-"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty"`
L1MessageSender *common.Address `json:"l1MessageSender,omitempty"`
SignatureHashType SignatureHashType `json:"signatureHashType"`
}
var dec txdata
var t Transaction
var dec txnjson
if err := json.Unmarshal(input, &dec); err != nil {
return err
return &Transaction{}, err
}
if dec.AccountNonce == nil {
return errors.New("missing required field 'nonce' for txdata")
return &Transaction{}, errors.New("missing required field 'nonce' for txdata")
}
t.AccountNonce = uint64(*dec.AccountNonce)
t.data.AccountNonce = uint64(*dec.AccountNonce)
if dec.Price == nil {
return errors.New("missing required field 'gasPrice' for txdata")
return &Transaction{}, errors.New("missing required field 'gasPrice' for txdata")
}
t.Price = (*big.Int)(dec.Price)
t.data.Price = (*big.Int)(dec.Price)
if dec.GasLimit == nil {
return errors.New("missing required field 'gas' for txdata")
return &Transaction{}, errors.New("missing required field 'gas' for txdata")
}
t.GasLimit = uint64(*dec.GasLimit)
t.data.GasLimit = uint64(*dec.GasLimit)
if dec.Recipient != nil {
t.Recipient = dec.Recipient
t.data.Recipient = dec.Recipient
}
if dec.L1MessageSender != nil {
t.L1MessageSender = dec.L1MessageSender
t.meta.L1MessageSender = dec.L1MessageSender
}
if dec.L1RollupTxId != nil {
t.L1RollupTxId = dec.L1RollupTxId
t.meta.L1RollupTxId = dec.L1RollupTxId
}
t.meta.SignatureHashType = dec.SignatureHashType
if dec.Amount == nil {
return errors.New("missing required field 'value' for txdata")
return &Transaction{}, errors.New("missing required field 'value' for txdata")
}
t.Amount = (*big.Int)(dec.Amount)
t.data.Amount = (*big.Int)(dec.Amount)
if dec.Payload == nil {
return errors.New("missing required field 'input' for txdata")
return &Transaction{}, errors.New("missing required field 'input' for txdata")
}
t.Payload = *dec.Payload
t.data.Payload = *dec.Payload
if dec.V == nil {
return errors.New("missing required field 'v' for txdata")
return &Transaction{}, errors.New("missing required field 'v' for txdata")
}
t.V = (*big.Int)(dec.V)
t.data.V = (*big.Int)(dec.V)
if dec.R == nil {
return errors.New("missing required field 'r' for txdata")
return &Transaction{}, errors.New("missing required field 'r' for txdata")
}
t.R = (*big.Int)(dec.R)
t.data.R = (*big.Int)(dec.R)
if dec.S == nil {
return errors.New("missing required field 's' for txdata")
return &Transaction{}, errors.New("missing required field 's' for txdata")
}
t.S = (*big.Int)(dec.S)
t.data.S = (*big.Int)(dec.S)
if dec.Hash != nil {
t.Hash = dec.Hash
t.data.Hash = dec.Hash
}
return nil
return &t, nil
}

View File

@ -48,7 +48,7 @@ func TestLegacyReceiptDecoding(t *testing.T) {
},
}
tx := NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil, nil, nil)
tx := NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil, nil, nil, SighashEIP155)
receipt := &Receipt{
Status: ReceiptStatusFailed,
CumulativeGasUsed: 1,
@ -156,7 +156,7 @@ func TestDeriveFields(t *testing.T) {
// Create a few transactions to have receipts for
txs := Transactions{
NewContractCreation(1, big.NewInt(1), 1, big.NewInt(1), nil, nil, nil),
NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil, nil, nil),
NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil, nil, nil, SighashEIP155),
}
// Create the corresponding receipts
receipts := Receipts{

View File

@ -36,8 +36,16 @@ var (
ErrInvalidSig = errors.New("invalid transaction v, r, s values")
)
type SignatureHashType uint8
const (
SighashEIP155 SignatureHashType = 0
SighashEthSign SignatureHashType = 1
)
type Transaction struct {
data txdata
meta TransactionMeta
// caches
hash atomic.Value
size atomic.Value
@ -58,9 +66,7 @@ type txdata struct {
S *big.Int `json:"s" gencodec:"required"`
// This is only used when marshaling to JSON.
Hash *common.Hash `json:"hash" rlp:"-"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty" rlp:"nil,?"`
L1MessageSender *common.Address `json:"l1MessageSender,omitempty" rlp:"nil,?"`
Hash *common.Hash `json:"hash" rlp:"-"`
}
type txdataMarshaling struct {
@ -74,30 +80,35 @@ type txdataMarshaling struct {
S *hexutil.Big
}
func NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, l1MessageSender *common.Address, l1RollupTxId *hexutil.Uint64) *Transaction {
return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data, l1MessageSender, l1RollupTxId)
func NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, l1MessageSender *common.Address, l1RollupTxId *hexutil.Uint64, sighashType SignatureHashType) *Transaction {
return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data, l1MessageSender, l1RollupTxId, sighashType)
}
func NewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, l1MessageSender *common.Address, l1RollupTxId *hexutil.Uint64) *Transaction {
return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data, l1MessageSender, l1RollupTxId)
return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data, l1MessageSender, l1RollupTxId, SighashEIP155)
}
func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, l1MessageSender *common.Address, l1RollupTxId *hexutil.Uint64) *Transaction {
func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, l1MessageSender *common.Address, l1RollupTxId *hexutil.Uint64, sighashType SignatureHashType) *Transaction {
if len(data) > 0 {
data = common.CopyBytes(data)
}
meta := TransactionMeta{
L1RollupTxId: l1RollupTxId,
L1MessageSender: l1MessageSender,
SignatureHashType: sighashType,
}
d := txdata{
AccountNonce: nonce,
Recipient: to,
L1MessageSender: l1MessageSender,
L1RollupTxId: l1RollupTxId,
Payload: data,
Amount: new(big.Int),
GasLimit: gasLimit,
Price: new(big.Int),
V: new(big.Int),
R: new(big.Int),
S: new(big.Int),
AccountNonce: nonce,
Recipient: to,
Payload: data,
Amount: new(big.Int),
GasLimit: gasLimit,
Price: new(big.Int),
V: new(big.Int),
R: new(big.Int),
S: new(big.Int),
}
if amount != nil {
d.Amount.Set(amount)
@ -106,7 +117,21 @@ func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit
d.Price.Set(gasPrice)
}
return &Transaction{data: d}
return &Transaction{data: d, meta: meta}
}
func (t *Transaction) SetTransactionMeta(meta *TransactionMeta) {
if meta == nil {
return
}
t.meta = *meta
}
func (t *Transaction) GetMeta() *TransactionMeta {
if &t.meta == nil {
return &TransactionMeta{}
}
return &t.meta
}
// Appends the provided 64-bit nonce to this Transaction's calldata as the last 4 bytes
@ -169,43 +194,49 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
// MarshalJSON encodes the web3 RPC transaction format.
func (tx *Transaction) MarshalJSON() ([]byte, error) {
hash := tx.Hash()
data := tx.data
data.Hash = &hash
return data.MarshalJSON()
return TransactionMarshalJSON(tx)
}
// UnmarshalJSON decodes the web3 RPC transaction format.
func (tx *Transaction) UnmarshalJSON(input []byte) error {
var dec txdata
if err := dec.UnmarshalJSON(input); err != nil {
dec, err := TransactionUnmarshalJSON(input)
if err != nil {
return err
}
withSignature := dec.V.Sign() != 0 || dec.R.Sign() != 0 || dec.S.Sign() != 0
withSignature := dec.data.V.Sign() != 0 || dec.data.R.Sign() != 0 || dec.data.S.Sign() != 0
if withSignature {
var V byte
if isProtectedV(dec.V) {
chainID := deriveChainId(dec.V).Uint64()
V = byte(dec.V.Uint64() - 35 - 2*chainID)
if isProtectedV(dec.data.V) {
chainID := deriveChainId(dec.data.V).Uint64()
V = byte(dec.data.V.Uint64() - 35 - 2*chainID)
} else {
V = byte(dec.V.Uint64() - 27)
V = byte(dec.data.V.Uint64() - 27)
}
if !crypto.ValidateSignatureValues(V, dec.R, dec.S, false) {
if !crypto.ValidateSignatureValues(V, dec.data.R, dec.data.S, false) {
return ErrInvalidSig
}
}
*tx = Transaction{data: dec}
*tx = *dec
return nil
}
func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) }
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
func (tx *Transaction) CheckNonce() bool { return true }
func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) }
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
func (tx *Transaction) CheckNonce() bool { return true }
func (tx *Transaction) SignatureHashType() SignatureHashType { return tx.meta.SignatureHashType }
func (tx *Transaction) SetSignatureHashType(sighashType SignatureHashType) {
tx.meta.SignatureHashType = sighashType
}
func (tx *Transaction) IsEthSignSighash() bool {
return tx.SignatureHashType() == SighashEthSign
}
// To returns the recipient address of the transaction.
// It returns nil if the transaction is a contract creation.
@ -220,20 +251,20 @@ func (tx *Transaction) To() *common.Address {
// L1MessageSender returns the L1 message sender address of the transaction if one exists.
// It returns nil if this transaction was not from an L1 contract.
func (tx *Transaction) L1MessageSender() *common.Address {
if tx.data.L1MessageSender == nil {
if tx.meta.L1MessageSender == nil {
return nil
}
l1MessageSender := *tx.data.L1MessageSender
l1MessageSender := *tx.meta.L1MessageSender
return &l1MessageSender
}
// L1RollupTxId returns the L1 Rollup Tx Id of the transaction if one exists.
// It returns nil if this transaction was not generated from a transaction received on L1.
func (tx *Transaction) L1RollupTxId() *hexutil.Uint64 {
if tx.data.L1RollupTxId == nil {
if tx.meta.L1RollupTxId == nil {
return nil
}
l1RolupTxId := *tx.data.L1RollupTxId
l1RolupTxId := *tx.meta.L1RollupTxId
return &l1RolupTxId
}
@ -244,20 +275,7 @@ func (tx *Transaction) Hash() common.Hash {
return hash.(common.Hash)
}
var sender *common.Address
var l1RollupTxId *hexutil.Uint64
if tx != nil {
sender = tx.data.L1MessageSender
tx.data.L1MessageSender = nil
l1RollupTxId = tx.data.L1RollupTxId
tx.data.L1RollupTxId = nil
}
v := rlpHash(tx)
if tx != nil {
tx.data.L1MessageSender = sender
tx.data.L1RollupTxId = l1RollupTxId
}
tx.hash.Store(v)
return v
}
@ -281,15 +299,16 @@ func (tx *Transaction) Size() common.StorageSize {
// XXX Rename message to something less arbitrary?
func (tx *Transaction) AsMessage(s Signer) (Message, error) {
msg := Message{
nonce: tx.data.AccountNonce,
gasLimit: tx.data.GasLimit,
gasPrice: new(big.Int).Set(tx.data.Price),
to: tx.data.Recipient,
l1MessageSender: tx.data.L1MessageSender,
l1RollupTxId: tx.data.L1RollupTxId,
amount: tx.data.Amount,
data: tx.data.Payload,
checkNonce: true,
nonce: tx.data.AccountNonce,
gasLimit: tx.data.GasLimit,
gasPrice: new(big.Int).Set(tx.data.Price),
to: tx.data.Recipient,
l1MessageSender: tx.meta.L1MessageSender,
l1RollupTxId: tx.meta.L1RollupTxId,
signatureHashType: tx.meta.SignatureHashType,
amount: tx.data.Amount,
data: tx.data.Payload,
checkNonce: true,
}
var err error
@ -304,7 +323,7 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
if err != nil {
return nil, err
}
cpy := &Transaction{data: tx.data}
cpy := &Transaction{data: tx.data, meta: tx.meta}
cpy.data.R, cpy.data.S, cpy.data.V = r, s, v
return cpy, nil
}
@ -402,12 +421,15 @@ func NewTransactionsByPriceAndNonce(signer Signer, txs map[common.Address]Transa
// Initialize a price based heap with the head transactions
heads := make(TxByPrice, 0, len(txs))
for from, accTxs := range txs {
heads = append(heads, accTxs[0])
// Ensure the sender address is from the signer
acc, _ := Sender(signer, accTxs[0])
txs[acc] = accTxs[1:]
if from != acc {
delete(txs, from)
// This prevents a panic, not ideal.
if len(accTxs) > 0 {
heads = append(heads, accTxs[0])
// Ensure the sender address is from the signer
acc, _ := Sender(signer, accTxs[0])
txs[acc] = accTxs[1:]
if from != acc {
delete(txs, from)
}
}
}
heap.Init(&heads)
@ -450,40 +472,43 @@ func (t *TransactionsByPriceAndNonce) Pop() {
//
// NOTE: In a future PR this will be removed.
type Message struct {
to *common.Address
l1MessageSender *common.Address
l1RollupTxId *hexutil.Uint64
from common.Address
nonce uint64
amount *big.Int
gasLimit uint64
gasPrice *big.Int
data []byte
checkNonce bool
to *common.Address
l1MessageSender *common.Address
l1RollupTxId *hexutil.Uint64
signatureHashType SignatureHashType
from common.Address
nonce uint64
amount *big.Int
gasLimit uint64
gasPrice *big.Int
data []byte
checkNonce bool
}
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool, l1MessageSender *common.Address, l1RollupTxId *hexutil.Uint64) Message {
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool, l1MessageSender *common.Address, l1RollupTxId *hexutil.Uint64, signatureHashType SignatureHashType) Message {
return Message{
from: from,
to: to,
nonce: nonce,
amount: amount,
gasLimit: gasLimit,
gasPrice: gasPrice,
data: data,
checkNonce: checkNonce,
l1RollupTxId: l1RollupTxId,
l1MessageSender: l1MessageSender,
from: from,
to: to,
nonce: nonce,
amount: amount,
gasLimit: gasLimit,
gasPrice: gasPrice,
data: data,
checkNonce: checkNonce,
l1RollupTxId: l1RollupTxId,
l1MessageSender: l1MessageSender,
signatureHashType: signatureHashType,
}
}
func (m Message) From() common.Address { return m.from }
func (m Message) To() *common.Address { return m.to }
func (m Message) L1MessageSender() *common.Address { return m.l1MessageSender }
func (m Message) L1RollupTxId() *hexutil.Uint64 { return m.l1RollupTxId }
func (m Message) GasPrice() *big.Int { return m.gasPrice }
func (m Message) Value() *big.Int { return m.amount }
func (m Message) Gas() uint64 { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data }
func (m Message) CheckNonce() bool { return m.checkNonce }
func (m Message) From() common.Address { return m.from }
func (m Message) To() *common.Address { return m.to }
func (m Message) L1MessageSender() *common.Address { return m.l1MessageSender }
func (m Message) L1RollupTxId() *hexutil.Uint64 { return m.l1RollupTxId }
func (m Message) SignatureHashType() SignatureHashType { return m.signatureHashType }
func (m Message) GasPrice() *big.Int { return m.gasPrice }
func (m Message) Value() *big.Int { return m.amount }
func (m Message) Gas() uint64 { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data }
func (m Message) CheckNonce() bool { return m.checkNonce }

View File

@ -0,0 +1,104 @@
/**
* Optimism 2020 Copyright
*/
package types
import (
"bytes"
"encoding/binary"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
type TransactionMeta struct {
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId"`
L1MessageSender *common.Address `json:"l1MessageSender"`
SignatureHashType SignatureHashType `json:"signatureHashType"`
}
func NewTransactionMeta(L1RollupTxId *hexutil.Uint64, L1MessageSender *common.Address, sighashType SignatureHashType) *TransactionMeta {
return &TransactionMeta{L1RollupTxId: L1RollupTxId, L1MessageSender: L1MessageSender, SignatureHashType: sighashType}
}
// TxMetaDecode deserializes bytes as a TransactionMeta struct.
// The schema is:
// varbytes(SignatureHashType) || varbytes(L1RollupTxId) || varbytes(L1MessageSender)
func TxMetaDecode(input []byte) (*TransactionMeta, error) {
var err error
meta := TransactionMeta{}
b := bytes.NewReader(input)
sb, err := common.ReadVarBytes(b, 0, 1024, "SignatureHashType")
if err != nil {
return &TransactionMeta{}, err
}
var sighashType SignatureHashType
binary.Read(bytes.NewReader(sb), binary.LittleEndian, &sighashType)
meta.SignatureHashType = sighashType
lb, err := common.ReadVarBytes(b, 0, 1024, "L1RollupTxId")
if err != nil {
return &TransactionMeta{}, err
}
if !isNullValue(lb) {
var l1RollupTxId hexutil.Uint64
binary.Read(bytes.NewReader(lb), binary.LittleEndian, &l1RollupTxId)
meta.L1RollupTxId = &l1RollupTxId
}
mb, err := common.ReadVarBytes(b, 0, 1024, "L1MessageSender")
if err != nil {
return &TransactionMeta{}, err
}
if !isNullValue(mb) {
var l1MessageSender common.Address
binary.Read(bytes.NewReader(mb), binary.LittleEndian, &l1MessageSender)
meta.L1MessageSender = &l1MessageSender
}
return &meta, nil
}
// TxMetaEncode serializes the TransactionMeta as bytes.
func TxMetaEncode(meta *TransactionMeta) []byte {
b := new(bytes.Buffer)
s := new(bytes.Buffer)
binary.Write(s, binary.LittleEndian, &meta.SignatureHashType)
common.WriteVarBytes(b, 0, s.Bytes())
L1RollupTxId := meta.L1RollupTxId
if L1RollupTxId == nil {
common.WriteVarBytes(b, 0, getNullValue())
} else {
l := new(bytes.Buffer)
binary.Write(l, binary.LittleEndian, *L1RollupTxId)
common.WriteVarBytes(b, 0, l.Bytes())
}
L1MessageSender := meta.L1MessageSender
if L1MessageSender == nil {
common.WriteVarBytes(b, 0, getNullValue())
} else {
l := new(bytes.Buffer)
binary.Write(l, binary.LittleEndian, *L1MessageSender)
common.WriteVarBytes(b, 0, l.Bytes())
}
return b.Bytes()
}
func isNullValue(b []byte) bool {
nullValue := []byte{0x00}
return bytes.Equal(b, nullValue)
}
func getNullValue() []byte {
return []byte{0x00}
}

View File

@ -0,0 +1,110 @@
package types
import (
"bytes"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var (
addr = common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
txid = hexutil.Uint64(0)
txMetaSerializationTests = []struct {
txid *hexutil.Uint64
msgSender *common.Address
sighashType SignatureHashType
}{
{
txid: &txid,
msgSender: &addr,
sighashType: SighashEthSign,
},
{
txid: nil,
msgSender: &addr,
sighashType: SighashEthSign,
},
{
txid: &txid,
msgSender: nil,
sighashType: SighashEthSign,
},
}
txMetaSighashEncodeTests = []struct {
input SignatureHashType
output SignatureHashType
}{
{
input: SighashEIP155,
output: SighashEIP155,
},
{
input: SighashEthSign,
output: SighashEthSign,
},
}
)
func TestTransactionMetaEncode(t *testing.T) {
for _, test := range txMetaSerializationTests {
txmeta := NewTransactionMeta(test.txid, test.msgSender, test.sighashType)
encoded := TxMetaEncode(txmeta)
decoded, err := TxMetaDecode(encoded)
if err != nil {
t.Fatal(err)
}
if !isTxMetaEqual(txmeta, decoded) {
t.Fatal("Encoding/decoding mismatch")
}
}
}
func TestTransactionSighashEncode(t *testing.T) {
for _, test := range txMetaSighashEncodeTests {
txmeta := NewTransactionMeta(&txid, &addr, test.input)
encoded := TxMetaEncode(txmeta)
decoded, err := TxMetaDecode(encoded)
if err != nil {
t.Fatal(err)
}
if decoded.SignatureHashType != test.output {
t.Fatal("SighashTypes do not match")
}
}
}
func isTxMetaEqual(meta1 *TransactionMeta, meta2 *TransactionMeta) bool {
if meta1.L1MessageSender == nil || meta2.L1MessageSender == nil {
if meta1.L1MessageSender != meta2.L1MessageSender {
return false
}
} else {
if !bytes.Equal(meta1.L1MessageSender.Bytes(), meta2.L1MessageSender.Bytes()) {
return false
}
}
if meta1.L1RollupTxId == nil || meta2.L1RollupTxId == nil {
if meta1.L1RollupTxId != meta2.L1RollupTxId {
return false
}
} else {
if *meta1.L1RollupTxId != *meta2.L1RollupTxId {
return false
}
}
if meta1.SignatureHashType != meta2.SignatureHashType {
return false
}
return true
}

View File

@ -17,7 +17,9 @@
package types
import (
"bytes"
"crypto/ecdsa"
"encoding/binary"
"errors"
"fmt"
"math/big"
@ -25,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"golang.org/x/crypto/sha3"
)
var (
@ -40,16 +43,7 @@ type sigCache struct {
// MakeSigner returns a Signer based on the given chain config and block number.
func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
var signer Signer
switch {
case config.IsEIP155(blockNumber):
signer = NewEIP155Signer(config.ChainID)
case config.IsHomestead(blockNumber):
signer = HomesteadSigner{}
default:
signer = FrontierSigner{}
}
return signer
return NewOVMSigner(config.ChainID)
}
// SignTx signs the transaction using the given signer and private key
@ -102,6 +96,102 @@ type Signer interface {
Equal(Signer) bool
}
// OVMSigner implements Signers using the EIP155 rules along with a new
// `eth_sign` based signature hash.
type OVMSigner struct {
EIP155Signer
}
func NewOVMSigner(chainId *big.Int) OVMSigner {
signer := NewEIP155Signer(chainId)
return OVMSigner{signer}
}
func (s OVMSigner) Equal(s2 Signer) bool {
ovm, ok := s2.(OVMSigner)
return ok && ovm.chainId.Cmp(s.chainId) == 0
}
// Hash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (s OVMSigner) Hash(tx *Transaction) common.Hash {
if tx.IsEthSignSighash() {
msg := s.OVMSignerTemplateSighashPreimage(tx)
hasher := sha3.NewLegacyKeccak256()
hasher.Write(msg)
digest := hasher.Sum(nil)
return common.BytesToHash(digest)
}
return rlpHash([]interface{}{
tx.data.AccountNonce,
tx.data.Price,
tx.data.GasLimit,
tx.data.Recipient,
tx.data.Amount,
tx.data.Payload,
s.chainId, uint(0), uint(0),
})
}
func (s OVMSigner) Sender(tx *Transaction) (common.Address, error) {
if !tx.Protected() {
return HomesteadSigner{}.Sender(tx)
}
if tx.ChainId().Cmp(s.chainId) != 0 {
return common.Address{}, ErrInvalidChainId
}
V := new(big.Int).Sub(tx.data.V, s.chainIdMul)
V.Sub(V, big8)
return recoverPlain(s.Hash(tx), tx.data.R, tx.data.S, V, true)
}
// OVMSignerTemplateSighashPreimage creates the preimage for the `eth_sign` like
// signature hash. The transaction is `ABI.encodePacked`.
func (s OVMSigner) OVMSignerTemplateSighashPreimage(tx *Transaction) []byte {
// Pad the nonce to 32 bytes
n := new(bytes.Buffer)
binary.Write(n, binary.BigEndian, tx.data.AccountNonce)
nonce := common.LeftPadBytes(n.Bytes(), 32)
// Pad the gas limit to 32 bytes
g := new(bytes.Buffer)
binary.Write(g, binary.BigEndian, tx.data.GasLimit)
gasLimit := common.LeftPadBytes(g.Bytes(), 32)
p := new(bytes.Buffer)
binary.Write(p, binary.BigEndian, tx.data.Price.Bytes())
gasPrice := common.LeftPadBytes(p.Bytes(), 32)
chainId := common.LeftPadBytes(s.chainId.Bytes(), 32)
// This should always be 20 bytes
to := tx.data.Recipient.Bytes()
// The signature hash commits to the nonce, gas limit,
// recipient and data
b := new(bytes.Buffer)
binary.Write(b, binary.BigEndian, nonce)
binary.Write(b, binary.BigEndian, gasLimit)
binary.Write(b, binary.BigEndian, gasPrice)
binary.Write(b, binary.BigEndian, chainId)
binary.Write(b, binary.BigEndian, to)
binary.Write(b, binary.BigEndian, tx.data.Payload)
hasher := sha3.NewLegacyKeccak256()
hasher.Write(b.Bytes())
digest := hasher.Sum(nil)
preimage := new(bytes.Buffer)
prefix := []byte("\x19Ethereum Signed Message:\n32")
binary.Write(preimage, binary.BigEndian, prefix)
binary.Write(preimage, binary.BigEndian, digest)
return preimage.Bytes()
}
// EIP155Transaction implements Signer using the EIP155 rules.
type EIP155Signer struct {
chainId, chainIdMul *big.Int

View File

@ -30,7 +30,7 @@ func TestEIP155Signing(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18))
tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil, nil, nil), signer, key)
tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEIP155), signer, key)
if err != nil {
t.Fatal(err)
}
@ -49,7 +49,7 @@ func TestEIP155ChainId(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18))
tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil, nil, nil), signer, key)
tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEIP155), signer, key)
if err != nil {
t.Fatal(err)
}
@ -61,7 +61,7 @@ func TestEIP155ChainId(t *testing.T) {
t.Error("expected chainId to be", signer.chainId, "got", tx.ChainId())
}
tx = NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil, nil, nil)
tx = NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEIP155)
tx, err = SignTx(tx, HomesteadSigner{}, key)
if err != nil {
t.Fatal(err)
@ -118,7 +118,7 @@ func TestEIP155SigningVitalik(t *testing.T) {
func TestChainId(t *testing.T) {
key, _ := defaultTestKey()
tx := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil, nil, nil)
tx := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEIP155)
var err error
tx, err = SignTx(tx, NewEIP155Signer(big.NewInt(1)), key)
@ -136,3 +136,94 @@ func TestChainId(t *testing.T) {
t.Error("expected no error")
}
}
func TestOVMSigner(t *testing.T) {
key, _ := defaultTestKey()
tx := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEthSign)
var err error
tx, err = SignTx(tx, NewOVMSigner(big.NewInt(1)), key)
if err != nil {
t.Fatal(err)
}
_, err = Sender(NewOVMSigner(big.NewInt(2)), tx)
if err != ErrInvalidChainId {
t.Error("expected error:", ErrInvalidChainId)
}
_, err = Sender(NewOVMSigner(big.NewInt(1)), tx)
if err != nil {
t.Error("expected no error")
}
}
func TestOVMSignerHash(t *testing.T) {
signer := NewOVMSigner(big.NewInt(1))
txNil := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEIP155)
txEIP155 := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEIP155)
hashNil := signer.Hash(txNil)
hashEIP155 := signer.Hash(txEIP155)
if hashNil != hashEIP155 {
t.Errorf("Signature hashes should be equal: %s != %s", hashNil.Hex(), hashEIP155.Hex())
}
// The signature hash should be different when using `SighashEthSign`
txEthSign := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEthSign)
hashEthSign := signer.Hash(txEthSign)
if hashEIP155 == hashEthSign {
t.Errorf("Signature hashes should not be equal: %s == %s", hashEIP155.Hex(), hashEthSign.Hex())
}
}
func TestOVMSignerSender(t *testing.T) {
// Create a keypair to sign transactions with and the corresponding address
// from the public key.
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
// This test makes sure that both the EIP155 and EthSign signature hash
// codepaths work when using the OVMSigner.
signer := NewOVMSigner(big.NewInt(1))
var err error
// Create a transaction with EIP155 signature hash, sign the transaction,
// recover the address and assert that the address matches the key.
txEIP155 := NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil, nil, nil, SighashEIP155)
txEIP155, err = SignTx(txEIP155, signer, key)
if err != nil {
t.Errorf("No error expected")
}
recEIP155, err := signer.Sender(txEIP155)
if err != nil {
t.Errorf("No error expected")
}
if addr != recEIP155 {
t.Errorf("Recovered address doesn't match. Got %s, expected %s", recEIP155.Hex(), addr.Hex())
}
// 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, nil, nil, SighashEthSign)
txEthSign, err = SignTx(txEthSign, signer, key)
if err != nil {
t.Errorf("No error expected")
}
recEthSign, err := signer.Sender(txEthSign)
if err != nil {
t.Errorf("No error expected")
}
if addr != recEthSign {
t.Errorf("Recovered address doesn't match. Got %s, expected %s", recEthSign.Hex(), addr.Hex())
}
}

View File

@ -35,23 +35,25 @@ import (
var (
sender = common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
l1RollupTxId = hexutil.Uint64(1)
emptyTx = NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(0), 0, big.NewInt(0), nil, &sender, nil)
emptyTxEmptyL1Sender = NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(0), 0, big.NewInt(0), nil, nil, nil)
emptyTx = NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(0), 0, big.NewInt(0), nil, &sender, nil, SighashEIP155)
emptyTxEmptyL1Sender = NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(0), 0, big.NewInt(0), nil, nil, nil, SighashEIP155)
rightvrsTx, _ = NewTransaction(3, common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), big.NewInt(10), 2000, big.NewInt(1), common.FromHex("5544"), nil, nil).WithSignature(
rightvrsTx, _ = NewTransaction(3, common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), big.NewInt(10), 2000, big.NewInt(1), common.FromHex("5544"), nil, nil, SighashEIP155).WithSignature(
HomesteadSigner{},
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a301"),
)
rightvrsTxWithL1Sender, _ = NewTransaction(3, common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), big.NewInt(10), 2000, big.NewInt(1), common.FromHex("5544"), &sender, nil).WithSignature(
rightvrsTxWithL1Sender, _ = NewTransaction(3, common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), big.NewInt(10), 2000, big.NewInt(1), common.FromHex("5544"), &sender, nil, SighashEIP155).WithSignature(
HomesteadSigner{},
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a301"),
)
rightvrsTxWithL1RollupTxId, _ = NewTransaction(3, common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), big.NewInt(10), 2000, big.NewInt(1), common.FromHex("5544"), nil, &l1RollupTxId).WithSignature(
rightvrsTxWithL1RollupTxId, _ = NewTransaction(3, common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), big.NewInt(10), 2000, big.NewInt(1), common.FromHex("5544"), nil, &l1RollupTxId, SighashEIP155).WithSignature(
HomesteadSigner{},
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a301"),
)
emptyTxSighashEthSign = NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(0), 0, big.NewInt(0), nil, &sender, nil, SighashEthSign)
)
func TestTransactionSigHash(t *testing.T) {
@ -78,16 +80,29 @@ func TestTransactionEncode(t *testing.T) {
if err != nil {
t.Fatalf("encode error: %v", err)
}
if bytes.Equal(txc, should) {
t.Errorf("RLP encoding with L1MessageSender should be different than without. Got %x", txc)
if !bytes.Equal(txc, should) {
t.Errorf("RLP encoding with L1MessageSender should be the same. Got %x", txc)
}
txd, err := rlp.EncodeToBytes(rightvrsTxWithL1RollupTxId)
if err != nil {
t.Fatalf("encode error: %v", err)
}
if bytes.Equal(txd, should) {
t.Errorf("RLP encoding with L1MessageSender should be different than without. Got %x", txd)
if !bytes.Equal(txd, should) {
t.Errorf("RLP encoding with L1MessageSender should be the same. Got %x", txd)
}
txe, err := rlp.EncodeToBytes(emptyTx)
if err != nil {
t.Fatalf("encode error: %v", err)
}
txf, err := rlp.EncodeToBytes(emptyTxSighashEthSign)
if err != nil {
t.Fatalf("encode error: %v", err)
}
if !bytes.Equal(txe, txf) {
t.Error("RLP encoding with SighashEthSign should be the same")
}
}
@ -153,7 +168,7 @@ func TestTransactionPriceNonceSort(t *testing.T) {
for start, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
for i := 0; i < 25; i++ {
tx, _ := SignTx(NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), 100, big.NewInt(int64(start+i)), nil, nil, nil), signer, key)
tx, _ := SignTx(NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), 100, big.NewInt(int64(start+i)), nil, nil, nil, SighashEIP155), signer, key)
groups[addr] = append(groups[addr], tx)
}
}
@ -197,14 +212,14 @@ func TestTransactionJSON(t *testing.T) {
if err != nil {
t.Fatalf("could not generate key: %v", err)
}
signer := NewEIP155Signer(common.Big1)
signer := NewOVMSigner(common.Big1)
transactions := make([]*Transaction, 0, 50)
for i := uint64(0); i < 25; i++ {
var tx *Transaction
switch i % 2 {
case 0:
tx = NewTransaction(i, common.Address{1}, common.Big0, 1, common.Big2, []byte("abcdef"), &sender, &l1RollupTxId)
tx = NewTransaction(i, common.Address{1}, common.Big0, 1, common.Big2, []byte("abcdef"), &sender, &l1RollupTxId, SighashEIP155)
case 1:
tx = NewContractCreation(i, common.Big0, 1, common.Big2, []byte("abcdef"), nil, nil)
}
@ -245,8 +260,8 @@ func TestTransactionJSON(t *testing.T) {
}
}
// Tests that L1MessageSender has no impact on hash
func TestL1MessageSenderHash(t *testing.T) {
// Tests that OVM metadata has no impact on hash
func TestOVMMetaDataHash(t *testing.T) {
if rightvrsTx.Hash() != rightvrsTxWithL1Sender.Hash() {
t.Errorf("L1MessageSender, should not affect the hash, want %x, got %x with L1MessageSender", rightvrsTx.Hash(), rightvrsTxWithL1Sender.Hash())
}
@ -258,4 +273,8 @@ func TestL1MessageSenderHash(t *testing.T) {
if emptyTx.Hash() != emptyTxEmptyL1Sender.Hash() {
t.Errorf("L1MessageSender, should not affect the hash, want %x, got %x with L1MessageSender", emptyTx.Hash(), emptyTxEmptyL1Sender.Hash())
}
if emptyTx.Hash() != emptyTxSighashEthSign.Hash() {
t.Errorf("SignatureHashType, should not affect the hash, want %x, got %x with SighashEthSign", emptyTx.Hash(), emptyTxSighashEthSign.Hash())
}
}

View File

@ -131,7 +131,7 @@ func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool)
signer := types.MakeSigner(params.TestChainConfig, block.Number())
l1Sender := common.Address{seed}
l1RollupTxId := hexutil.Uint64(22)
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil, &l1Sender, &l1RollupTxId), signer, testKey)
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil, &l1Sender, &l1RollupTxId, types.SighashEIP155), signer, testKey)
if err != nil {
panic(err)
}

View File

@ -52,7 +52,7 @@ func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common
// If the block number is multiple of 3, send a bonus transaction to the miner
if parent == genesis && i%3 == 0 {
signer := types.MakeSigner(params.TestChainConfig, block.Number())
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, testKey)
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, testKey)
if err != nil {
panic(err)
}

View File

@ -218,11 +218,11 @@ func TestPendingTxFilter(t *testing.T) {
api = NewPublicFilterAPI(backend, false)
transactions = []*types.Transaction{
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil),
types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil),
types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil),
types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil),
types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil),
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil, types.SighashEIP155),
types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil, types.SighashEIP155),
types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil, types.SighashEIP155),
types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil, types.SighashEIP155),
types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil, nil, nil, types.SighashEIP155),
}
hashes []common.Hash

View File

@ -127,7 +127,7 @@ func TestFilters(t *testing.T) {
},
}
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil, nil, nil))
gen.AddUncheckedTx(types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil, nil, nil, types.SighashEIP155))
case 2:
receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{
@ -137,7 +137,7 @@ func TestFilters(t *testing.T) {
},
}
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil, nil, nil))
gen.AddUncheckedTx(types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil, nil, nil, types.SighashEIP155))
case 998:
receipt := types.NewReceipt(nil, false, 0)
@ -148,7 +148,7 @@ func TestFilters(t *testing.T) {
},
}
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(998, common.HexToAddress("0x998"), big.NewInt(998), 998, big.NewInt(998), nil, nil, nil))
gen.AddUncheckedTx(types.NewTransaction(998, common.HexToAddress("0x998"), big.NewInt(998), 998, big.NewInt(998), nil, nil, nil, types.SighashEIP155))
case 999:
receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{
@ -158,7 +158,7 @@ func TestFilters(t *testing.T) {
},
}
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, big.NewInt(999), nil, nil, nil))
gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, big.NewInt(999), nil, nil, nil, types.SighashEIP155))
}
})
for i, block := range chain {

View File

@ -290,13 +290,13 @@ func testGetNodeData(t *testing.T, protocol int) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil), signer, testBankKey)
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, testBankKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, acc1Key)
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, testBankKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
@ -389,13 +389,13 @@ func testGetReceipt(t *testing.T, protocol int) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil), signer, testBankKey)
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, testBankKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, acc1Key)
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, testBankKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:

View File

@ -134,7 +134,7 @@ func (p *testTxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subs
// newTestTransaction create a new dummy transaction.
func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction {
tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, datasize), nil, nil)
tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, datasize), nil, nil, types.SighashEIP155)
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, from)
return tx
}

View File

@ -123,7 +123,7 @@ type callTracerTest struct {
func TestPrestateTracerCreate2(t *testing.T) {
t.Skip("OVM breaks this with `cannot read property` error, probably related to state manager.")
unsignedTx := types.NewTransaction(1, common.HexToAddress("0x00000000000000000000000000000000deadbeef"), new(big.Int), 5000000, big.NewInt(1), []byte{}, nil, nil)
unsignedTx := types.NewTransaction(1, common.HexToAddress("0x00000000000000000000000000000000deadbeef"), new(big.Int), 5000000, big.NewInt(1), []byte{}, nil, nil, types.SighashEIP155)
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
if err != nil {

View File

@ -830,7 +830,7 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
}
// Create new call message
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false, nil, nil)
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false, nil, nil, 0)
// Setup context so it may be cancelled the call has completed
// or, in case of unmetered gas, setup a context with a timeout.
@ -1117,9 +1117,10 @@ type RPCTransaction struct {
// newRPCTransaction returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available).
func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64) *RPCTransaction {
// TODO(mark): the transaction must be protected
var signer types.Signer = types.FrontierSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
signer = types.NewOVMSigner(tx.ChainId())
}
from, _ := types.Sender(signer, tx)
v, r, s := tx.RawSignatureValues()
@ -1269,6 +1270,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
// Try to return an already finalized transaction
tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
if err != nil {
return nil, err
}
@ -1318,7 +1320,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
var signer types.Signer = types.FrontierSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
signer = types.NewOVMSigner(tx.ChainId())
}
from, _ := types.Sender(signer, tx)
@ -1375,10 +1377,11 @@ type SendTxArgs struct {
Nonce *hexutil.Uint64 `json:"nonce"`
// We accept "data" and "input" for backwards-compatibility reasons. "input" is the
// newer name and should be preferred by clients.
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty" rlp:"nil,?"`
L1MessageSender *common.Address `json:"l1MessageSender,omitempty" rlp:"nil,?"`
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty"`
L1MessageSender *common.Address `json:"l1MessageSender,omitempty"`
SignatureHashType types.SignatureHashType `json:"signatureHashType,omitempty"`
}
// setDefaults is a helper function that fills in default values for unspecified tx fields.
@ -1451,7 +1454,7 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
if args.To == nil {
return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input, nil, args.L1RollupTxId)
}
return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input, args.L1MessageSender, args.L1RollupTxId)
return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input, args.L1MessageSender, args.L1RollupTxId, args.SignatureHashType)
}
type RollupTransaction struct {
@ -1471,7 +1474,7 @@ func (r *RollupTransaction) toTransaction(txNonce uint64) *types.Transaction {
if r.Target == nil {
tx = types.NewContractCreation(txNonce, big.NewInt(0), uint64(*r.GasLimit), big.NewInt(0), c, r.Sender, r.L1RollupTxId)
} else {
tx = types.NewTransaction(txNonce, *r.Target, big.NewInt(0), uint64(*r.GasLimit), big.NewInt(0), c, r.Sender, r.L1RollupTxId)
tx = types.NewTransaction(txNonce, *r.Target, big.NewInt(0), uint64(*r.GasLimit), big.NewInt(0), c, r.Sender, r.L1RollupTxId, types.SighashEIP155)
}
tx.AddNonceToWrappedTransaction(uint64(*r.Nonce))
return tx
@ -1561,7 +1564,21 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
return SubmitTransaction(ctx, s.b, tx)
}
// SendBlockBatches will:
// SendRawEthSignTransaction will add the signed transaction to the mempool.
// The signature hash was computed with `eth_sign`, meaning that the
// `abi.encodedPacked` transaction was prefixed with the string
// "Ethereum Signed Message".
func (s *PublicTransactionPoolAPI) SendRawEthSignTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
tx := new(types.Transaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err
}
tx.SetSignatureHashType(types.SighashEthSign)
return SubmitTransaction(ctx, s.b, tx)
}
// SendRollupTransactions will:
// * Verify the batches are signed by the RollupTransaction sender.
// * Update the Geth timestamp to the provided timestamp
// * handle the provided batch of RollupTransactions atomically
@ -1680,7 +1697,7 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
for _, tx := range pending {
var signer types.Signer = types.HomesteadSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
signer = types.NewOVMSigner(tx.ChainId())
}
from, _ := types.Sender(signer, tx)
if _, exists := accounts[from]; exists {
@ -1708,7 +1725,7 @@ func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxAr
for _, p := range pending {
var signer types.Signer = types.HomesteadSigner{}
if p.Protected() {
signer = types.NewEIP155Signer(p.ChainId())
signer = types.NewOVMSigner(p.ChainId())
}
wantSigHash := signer.Hash(matchTx)

View File

@ -180,7 +180,7 @@ func (b *benchmarkTxSend) init(h *serverHandler, count int) error {
for i := range b.txs {
data := make([]byte, txSizeCostLimit)
rand.Read(data)
tx, err := types.SignTx(types.NewTransaction(0, addr, new(big.Int), 0, new(big.Int), data, nil, nil), signer, key)
tx, err := types.SignTx(types.NewTransaction(0, addr, new(big.Int), 0, new(big.Int), data, nil, nil, types.SighashEIP155), signer, key)
if err != nil {
panic(err)
}

View File

@ -556,16 +556,16 @@ func testTransactionStatus(t *testing.T, protocol int) {
signer := types.HomesteadSigner{}
// test error status by sending an underpriced transaction
tx0, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, nil, nil, nil, nil), signer, bankKey)
tx0, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, bankKey)
test(tx0, true, light.TxStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced.Error()})
tx1, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil, nil, nil), signer, bankKey)
tx1, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil, nil, nil, types.SighashEIP155), signer, bankKey)
test(tx1, false, light.TxStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown
test(tx1, true, light.TxStatus{Status: core.TxStatusPending}) // send valid processable tx, should return pending
test(tx1, true, light.TxStatus{Status: core.TxStatusPending}) // adding it again should not return an error
tx2, _ := types.SignTx(types.NewTransaction(1, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil, nil, nil), signer, bankKey)
tx3, _ := types.SignTx(types.NewTransaction(2, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil, nil, nil), signer, bankKey)
tx2, _ := types.SignTx(types.NewTransaction(1, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil, nil, nil, types.SighashEIP155), signer, bankKey)
tx3, _ := types.SignTx(types.NewTransaction(2, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil, nil, nil, types.SighashEIP155), signer, bankKey)
// send transactions in the wrong order, tx3 should be queued
test(tx3, true, light.TxStatus{Status: core.TxStatusQueued})
test(tx2, true, light.TxStatus{Status: core.TxStatusPending})

View File

@ -160,7 +160,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
from := statedb.GetOrNewStateObject(bankAddr)
from.SetBalance(math.MaxBig256)
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, nil, nil)}
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, nil, nil, 0)}
context := core.NewEVMContext(msg, header, bc, nil)
vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
@ -174,7 +174,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
header := lc.GetHeaderByHash(bhash)
state := light.NewState(ctx, header, lc.Odr())
state.SetBalance(bankAddr, math.MaxBig256)
msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, nil, nil)}
msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, nil, nil, 0)}
context := core.NewEVMContext(msg, header, lc, nil)
vmenv := vm.NewEVM(context, state, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)

View File

@ -112,18 +112,18 @@ func prepare(n int, backend *backends.SimulatedBackend) {
registrarAddr, _, _, _ = contract.DeployCheckpointOracle(bind.NewKeyedTransactor(bankKey), backend, []common.Address{signerAddr}, sectionSize, processConfirms, big.NewInt(1))
// bankUser transfers some ether to user1
nonce, _ := backend.PendingNonceAt(ctx, bankAddr)
tx, _ := types.SignTx(types.NewTransaction(nonce, userAddr1, big.NewInt(10000), params.TxGas, nil, nil, nil, nil), signer, bankKey)
tx, _ := types.SignTx(types.NewTransaction(nonce, userAddr1, big.NewInt(10000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, bankKey)
backend.SendTransaction(ctx, tx)
case 1:
bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr)
userNonce1, _ := backend.PendingNonceAt(ctx, userAddr1)
// bankUser transfers more ether to user1
tx1, _ := types.SignTx(types.NewTransaction(bankNonce, userAddr1, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, bankKey)
tx1, _ := types.SignTx(types.NewTransaction(bankNonce, userAddr1, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, bankKey)
backend.SendTransaction(ctx, tx1)
// user1 relays ether to user2
tx2, _ := types.SignTx(types.NewTransaction(userNonce1, userAddr2, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, userKey1)
tx2, _ := types.SignTx(types.NewTransaction(userNonce1, userAddr2, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, userKey1)
backend.SendTransaction(ctx, tx2)
// user1 deploys a test contract
@ -137,18 +137,18 @@ func prepare(n int, backend *backends.SimulatedBackend) {
case 2:
// bankUser transfer some ether to signer
bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr)
tx1, _ := types.SignTx(types.NewTransaction(bankNonce, signerAddr, big.NewInt(1000000000), params.TxGas, nil, nil, nil, nil), signer, bankKey)
tx1, _ := types.SignTx(types.NewTransaction(bankNonce, signerAddr, big.NewInt(1000000000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, bankKey)
backend.SendTransaction(ctx, tx1)
// invoke test contract
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx2, _ := types.SignTx(types.NewTransaction(bankNonce+1, testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil), signer, bankKey)
tx2, _ := types.SignTx(types.NewTransaction(bankNonce+1, testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil, types.SighashEIP155), signer, bankKey)
backend.SendTransaction(ctx, tx2)
case 3:
// invoke test contract
bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.SignTx(types.NewTransaction(bankNonce, testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil), signer, bankKey)
tx, _ := types.SignTx(types.NewTransaction(bankNonce, testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil, types.SighashEIP155), signer, bankKey)
backend.SendTransaction(ctx, tx)
}
backend.Commit()

View File

@ -194,7 +194,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
// Perform read-only call.
st.SetBalance(testBankAddress, math.MaxBig256)
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false, nil, nil)}
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false, nil, nil, 0)}
context := core.NewEVMContext(msg, header, chain, nil)
vmenv := vm.NewEVM(context, st, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
@ -212,15 +212,15 @@ func testChainGen(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil), signer, testBankKey)
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
// acc1Addr creates a test contract.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, testBankKey)
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, testBankKey)
nonce := block.TxNonce(acc1Addr)
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), signer, acc1Key)
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), signer, acc1Key)
nonce++
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 1000000, big.NewInt(0), testContractCode, nil, nil), signer, acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
@ -232,7 +232,7 @@ func testChainGen(i int, block *core.BlockGen) {
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil), signer, testBankKey)
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil, types.SighashEIP155), signer, testBankKey)
block.AddTx(tx)
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
@ -243,7 +243,7 @@ func testChainGen(i int, block *core.BlockGen) {
b3.Extra = []byte("foo")
block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil), signer, testBankKey)
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data, nil, nil, types.SighashEIP155), signer, testBankKey)
block.AddTx(tx)
}
}

View File

@ -77,7 +77,7 @@ func txPoolTestChainGen(i int, block *core.BlockGen) {
func TestTxPool(t *testing.T) {
for i := range testTx {
testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil), types.HomesteadSigner{}, testBankKey)
testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, testBankKey)
}
var (

View File

@ -82,9 +82,9 @@ func init() {
Period: 10,
Epoch: 30000,
}
tx1, _ := types.SignTx(types.NewTransaction(0, testUserAddress, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), types.HomesteadSigner{}, testBankKey)
tx1, _ := types.SignTx(types.NewTransaction(0, testUserAddress, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, testBankKey)
pendingTxs = append(pendingTxs, tx1)
tx2, _ := types.SignTx(types.NewTransaction(1, testUserAddress, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), types.HomesteadSigner{}, testBankKey)
tx2, _ := types.SignTx(types.NewTransaction(1, testUserAddress, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, testBankKey)
newTxs = append(newTxs, tx2)
rand.Seed(time.Now().UnixNano())
}
@ -171,7 +171,7 @@ func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction {
if creation {
tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(testBankAddress), big.NewInt(0), testGas, nil, common.FromHex(testCode), nil, nil), types.HomesteadSigner{}, testBankKey)
} else {
tx, _ = types.SignTx(types.NewTransaction(b.txPool.Nonce(testBankAddress), testUserAddress, big.NewInt(1000), params.TxGas, nil, nil, nil, nil), types.HomesteadSigner{}, testBankKey)
tx, _ = types.SignTx(types.NewTransaction(b.txPool.Nonce(testBankAddress), testUserAddress, big.NewInt(1000), params.TxGas, nil, nil, nil, nil, types.SighashEIP155), types.HomesteadSigner{}, testBankKey)
}
return tx
}

View File

@ -203,7 +203,7 @@ func NewTransaction(nonce int64, to *Address, amount *BigInt, gasLimit int64, ga
if to == nil {
return &Transaction{types.NewContractCreation(uint64(nonce), amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data), nil, nil)}
}
return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data), nil, nil)}
return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data), nil, nil, types.SighashEIP155)}
}
// NewTransactionFromRLP parses a transaction from an RLP data dump.

View File

@ -78,7 +78,7 @@ func createBlocks(number int, startIndex int, withTx bool) types.Blocks {
header := &types.Header{Number: big.NewInt(int64(i + startIndex))}
txs := make(types.Transactions, 0)
if withTx {
tx, _ := types.SignTx(types.NewTransaction(uint64(i), testUserAddress, big.NewInt(1), params.TxGas, big.NewInt(0), nil, &testUserAddress, &testRollupTxId), types.HomesteadSigner{}, testBankKey)
tx, _ := types.SignTx(types.NewTransaction(uint64(i), testUserAddress, big.NewInt(1), params.TxGas, big.NewInt(0), nil, &testUserAddress, &testRollupTxId, types.SighashEIP155), types.HomesteadSigner{}, testBankKey)
txs = append(txs, tx)
}
block := types.NewBlock(header, txs, make([]*types.Header, 0), make([]*types.Receipt, 0))

View File

@ -74,10 +74,11 @@ type SendTxArgs struct {
Value hexutil.Big `json:"value"`
Nonce hexutil.Uint64 `json:"nonce"`
// We accept "data" and "input" for backwards-compatibility reasons.
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input,omitempty"`
L1MessageSender *common.MixedcaseAddress `json:"l1MessageSender,omitempty" rlp:"nil,?"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty" rlp:"nil,?"`
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input,omitempty"`
L1MessageSender *common.MixedcaseAddress `json:"l1MessageSender,omitempty"`
L1RollupTxId *hexutil.Uint64 `json:"l1RollupTxId,omitempty"`
SignatureHashType types.SignatureHashType `json:"signatureHashType,omitempty"`
}
func (args SendTxArgs) String() string {
@ -105,5 +106,6 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
l1RollupTxId = new(hexutil.Uint64)
*l1RollupTxId = *args.L1RollupTxId
}
return types.NewTransaction(uint64(args.Nonce), args.To.Address(), (*big.Int)(&args.Value), (uint64)(args.Gas), (*big.Int)(&args.GasPrice), input, l1MessageSender, l1RollupTxId)
return types.NewTransaction(uint64(args.Nonce), args.To.Address(), (*big.Int)(&args.Value), (uint64)(args.Gas), (*big.Int)(&args.GasPrice), input, l1MessageSender, l1RollupTxId, args.SignatureHashType)
}

View File

@ -458,7 +458,7 @@ func dummySigned(value *big.Int) *types.Transaction {
gas := uint64(21000)
gasPrice := big.NewInt(2000000)
data := make([]byte, 0)
return types.NewTransaction(3, to, value, gas, gasPrice, data, nil, nil)
return types.NewTransaction(3, to, value, gas, gasPrice, data, nil, nil, types.SighashEIP155)
}
func TestLimitWindow(t *testing.T) {

View File

@ -241,6 +241,7 @@ func applyMessageToState(currentState *state.StateDB, from common.Address, to co
false,
&ZERO_ADDRESS,
nil,
0,
)
} else {
// Otherwise we actually use the `to` field!
@ -255,6 +256,7 @@ func applyMessageToState(currentState *state.StateDB, from common.Address, to co
false,
&ZERO_ADDRESS,
nil,
0,
)
}

View File

@ -279,7 +279,7 @@ func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) {
return nil, fmt.Errorf("invalid tx data %q", dataHex)
}
msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, data, true, nil, nil)
msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, data, true, nil, nil, 0)
return msg, nil
}