From 4e599ee469223ccc452f40f36c85bac3bea9c16b Mon Sep 17 00:00:00 2001
From: aaronbuchwald <aaron.buchwald56@gmail.com>
Date: Wed, 6 Oct 2021 07:12:52 -0400
Subject: [PATCH] core/types: copy tx recipient address (#23376)

This resolves a long-standing TODO. The point of copying the address is
to ensure that all data referenced by types.Transaction is independent of the
data passed into the constructor.

Co-authored-by: Felix Lange <fjl@twurst.com>
---
 core/types/access_list_tx.go |  3 +--
 core/types/dynamic_fee_tx.go |  3 +--
 core/types/legacy_tx.go      |  2 +-
 core/types/transaction.go    | 17 ++++++++++-------
 4 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/core/types/access_list_tx.go b/core/types/access_list_tx.go
index d8d08b48c..ee5f194b7 100644
--- a/core/types/access_list_tx.go
+++ b/core/types/access_list_tx.go
@@ -59,7 +59,7 @@ type AccessListTx struct {
 func (tx *AccessListTx) copy() TxData {
 	cpy := &AccessListTx{
 		Nonce: tx.Nonce,
-		To:    tx.To, // TODO: copy pointed-to address
+		To:    copyAddressPtr(tx.To),
 		Data:  common.CopyBytes(tx.Data),
 		Gas:   tx.Gas,
 		// These are copied below.
@@ -96,7 +96,6 @@ func (tx *AccessListTx) copy() TxData {
 // accessors for innerTx.
 func (tx *AccessListTx) txType() byte           { return AccessListTxType }
 func (tx *AccessListTx) chainID() *big.Int      { return tx.ChainID }
-func (tx *AccessListTx) protected() bool        { return true }
 func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
 func (tx *AccessListTx) data() []byte           { return tx.Data }
 func (tx *AccessListTx) gas() uint64            { return tx.Gas }
diff --git a/core/types/dynamic_fee_tx.go b/core/types/dynamic_fee_tx.go
index c6719a408..585c029d8 100644
--- a/core/types/dynamic_fee_tx.go
+++ b/core/types/dynamic_fee_tx.go
@@ -43,7 +43,7 @@ type DynamicFeeTx struct {
 func (tx *DynamicFeeTx) copy() TxData {
 	cpy := &DynamicFeeTx{
 		Nonce: tx.Nonce,
-		To:    tx.To, // TODO: copy pointed-to address
+		To:    copyAddressPtr(tx.To),
 		Data:  common.CopyBytes(tx.Data),
 		Gas:   tx.Gas,
 		// These are copied below.
@@ -84,7 +84,6 @@ func (tx *DynamicFeeTx) copy() TxData {
 // accessors for innerTx.
 func (tx *DynamicFeeTx) txType() byte           { return DynamicFeeTxType }
 func (tx *DynamicFeeTx) chainID() *big.Int      { return tx.ChainID }
-func (tx *DynamicFeeTx) protected() bool        { return true }
 func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
 func (tx *DynamicFeeTx) data() []byte           { return tx.Data }
 func (tx *DynamicFeeTx) gas() uint64            { return tx.Gas }
diff --git a/core/types/legacy_tx.go b/core/types/legacy_tx.go
index 514010ebb..cb86bed77 100644
--- a/core/types/legacy_tx.go
+++ b/core/types/legacy_tx.go
@@ -62,7 +62,7 @@ func NewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPric
 func (tx *LegacyTx) copy() TxData {
 	cpy := &LegacyTx{
 		Nonce: tx.Nonce,
-		To:    tx.To, // TODO: copy pointed-to address
+		To:    copyAddressPtr(tx.To),
 		Data:  common.CopyBytes(tx.Data),
 		Gas:   tx.Gas,
 		// These are initialized below.
diff --git a/core/types/transaction.go b/core/types/transaction.go
index e21cf2bda..83f1766e6 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -284,13 +284,7 @@ func (tx *Transaction) Nonce() uint64 { return tx.inner.nonce() }
 // To returns the recipient address of the transaction.
 // For contract-creation transactions, To returns nil.
 func (tx *Transaction) To() *common.Address {
-	// Copy the pointed-to address.
-	ito := tx.inner.to()
-	if ito == nil {
-		return nil
-	}
-	cpy := *ito
-	return &cpy
+	return copyAddressPtr(tx.inner.to())
 }
 
 // Cost returns gas * gasPrice + value.
@@ -632,3 +626,12 @@ func (m Message) Nonce() uint64          { return m.nonce }
 func (m Message) Data() []byte           { return m.data }
 func (m Message) AccessList() AccessList { return m.accessList }
 func (m Message) IsFake() bool           { return m.isFake }
+
+// copyAddressPtr copies an address.
+func copyAddressPtr(a *common.Address) *common.Address {
+	if a == nil {
+		return nil
+	}
+	cpy := *a
+	return &cpy
+}
-- 
GitLab