Skip to content

Commit

Permalink
Merge commit 'polygon/v1.0.2-beta' into release/polygon-1.x-fh2.3
Browse files Browse the repository at this point in the history
# Conflicts:
#	packaging/templates/package_scripts/control
#	packaging/templates/package_scripts/control.arm64
#	packaging/templates/package_scripts/control.profile.amd64
#	packaging/templates/package_scripts/control.profile.arm64
#	packaging/templates/package_scripts/control.validator
#	packaging/templates/package_scripts/control.validator.arm64
#	params/version.go
  • Loading branch information
maoueh committed Sep 13, 2023
2 parents 22d09de + 1f9c6bb commit 2486d3e
Show file tree
Hide file tree
Showing 32 changed files with 740 additions and 29 deletions.
9 changes: 8 additions & 1 deletion common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ import (
"reflect"
"strings"

"github.com/ethereum/go-ethereum/common/hexutil"
"golang.org/x/crypto/sha3"

"github.com/ethereum/go-ethereum/common/hexutil"
)

// Lengths of hashes and addresses in bytes.
Expand Down Expand Up @@ -66,6 +67,12 @@ func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
// If b is larger than len(h), b will be cropped from the left.
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }

func HexToRefHash(s string) *Hash {
v := BytesToHash(FromHex(s))

return &v
}

// Bytes gets the byte representation of the underlying hash.
func (h Hash) Bytes() []byte { return h[:] }

Expand Down
66 changes: 66 additions & 0 deletions core/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ import (
"math/big"
"testing"

"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/firehose"
Expand Down Expand Up @@ -274,3 +277,66 @@ func compareStateObjects(so0, so1 *stateObject, t *testing.T) {
}
}
}

func TestValidateKnownAccounts(t *testing.T) {
t.Parallel()

knownAccounts := make(types.KnownAccounts)

types.InsertKnownAccounts(knownAccounts, common.HexToAddress("0xadd1add1add1add1add1add1add1add1add1add1"), common.HexToHash("0x2d6f8a898e7dec0bb7a50e8c142be32d7c98c096ff68ed57b9b08280d9aca1ce"))
types.InsertKnownAccounts(knownAccounts, common.HexToAddress("0xadd2add2add2add2add2add2add2add2add2add2"), map[common.Hash]common.Hash{
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000aaa"): common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000bbb"),
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000ccc"): common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000ddd"),
})

stateobjaddr1 := common.HexToAddress("0xadd1add1add1add1add1add1add1add1add1add1")
stateobjaddr2 := common.HexToAddress("0xadd2add2add2add2add2add2add2add2add2add2")

storageaddr1 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000zzz")
storageaddr21 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000aaa")
storageaddr22 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000ccc")

data1 := common.BytesToHash([]byte{24})
data21 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000bbb")
data22 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000ddd")

s := newStateTest()

// set initial state object value
s.state.SetState(stateobjaddr1, storageaddr1, data1, firehose.NoOpContext)
s.state.SetState(stateobjaddr2, storageaddr21, data21, firehose.NoOpContext)
s.state.SetState(stateobjaddr2, storageaddr22, data22, firehose.NoOpContext)

require.NoError(t, s.state.ValidateKnownAccounts(knownAccounts))

types.InsertKnownAccounts(knownAccounts, common.HexToAddress("0xadd1add1add1add1add1add1add1add1add1add2"), common.HexToHash("0x2d6f8a898e7dec0bb7a50e8c142be32d7c98c096ff68ed57b9b08280d9aca1cf"))

stateobjaddr3 := common.HexToAddress("0xadd1add1add1add1add1add1add1add1add1add2")
storageaddr3 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000yyy")
data3 := common.BytesToHash([]byte{24})

s.state.SetState(stateobjaddr3, storageaddr3, data3, firehose.NoOpContext)

// expected error
err := s.state.ValidateKnownAccounts(knownAccounts)
require.Error(t, err, "should have been an error")

// correct the previous mistake "0x2d6f8a898e7dec0bb7a50e8c142be32d7c98c096ff68ed57b9b08280d9aca1cf" -> "0x2d6f8a898e7dec0bb7a50e8c142be32d7c98c096ff68ed57b9b08280d9aca1ce"
types.InsertKnownAccounts(knownAccounts, common.HexToAddress("0xadd1add1add1add1add1add1add1add1add1add2"), common.HexToHash("0x2d6f8a898e7dec0bb7a50e8c142be32d7c98c096ff68ed57b9b08280d9aca1ce"))
types.InsertKnownAccounts(knownAccounts, common.HexToAddress("0xadd2add2add2add2add2add2add2add2add2add3"), map[common.Hash]common.Hash{
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000aaa"): common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000bbb"),
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000ccc"): common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000ddd"),
})

stateobjaddr4 := common.HexToAddress("0xadd2add2add2add2add2add2add2add2add2add3")
storageaddr41 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000aaa")
storageaddr42 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000ccc")
data4 := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000bbb")

s.state.SetState(stateobjaddr4, storageaddr41, data4, firehose.NoOpContext)
s.state.SetState(stateobjaddr4, storageaddr42, data4, firehose.NoOpContext)

// expected error
err = s.state.ValidateKnownAccounts(knownAccounts)
require.Error(t, err, "should have been an error")
}
33 changes: 33 additions & 0 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -1655,6 +1655,39 @@ func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addre
return s.accessList.Contains(addr, slot)
}

func (s *StateDB) ValidateKnownAccounts(knownAccounts types.KnownAccounts) error {
if knownAccounts == nil {
return nil
}

for k, v := range knownAccounts {
// check if the value is hex string or an object
switch {
case v.IsSingle():
trie, _ := s.StorageTrie(k)
if trie != nil {
actualRootHash := trie.Hash()
if *v.Single != actualRootHash {
return fmt.Errorf("invalid root hash for: %v root hash: %v actual root hash: %v", k, v.Single, actualRootHash)
}
} else {
return fmt.Errorf("Storage Trie is nil for: %v", k)
}
case v.IsStorage():
for slot, value := range v.Storage {
actualValue := s.GetState(k, slot)
if value != actualValue {
return fmt.Errorf("invalid slot value at address: %v slot: %v value: %v actual value: %v", k, slot, value, actualValue)
}
}
default:
return fmt.Errorf("impossible to validate known accounts: %v", k)
}
}

return nil
}

// convertAccountSet converts a provided account set from address keyed to hash keyed.
func (s *StateDB) convertAccountSet(set map[common.Address]struct{}) map[common.Hash]struct{} {
ret := make(map[common.Hash]struct{})
Expand Down
27 changes: 27 additions & 0 deletions core/txpool/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/ethereum/go-ethereum/common"
cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
)
Expand Down Expand Up @@ -563,6 +564,32 @@ func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactio
return removed, invalids
}

// FilterTxConditional returns the conditional transactions with invalid KnownAccounts
// TODO - We will also have to check block range and time stamp range!
func (l *list) FilterTxConditional(state *state.StateDB) types.Transactions {
removed := l.txs.filter(func(tx *types.Transaction) bool {
if options := tx.GetOptions(); options != nil {
err := state.ValidateKnownAccounts(options.KnownAccounts)
if err != nil {
log.Error("Error while Filtering Tx Conditional", "err", err)
return true
}

return false
}

return false
})

if len(removed) == 0 {
return nil
}

l.txs.reheap(true)

return removed
}

// Cap places a hard limit on the number of items, returning all transactions
// exceeding that limit.
func (l *list) Cap(threshold int) types.Transactions {
Expand Down
65 changes: 65 additions & 0 deletions core/txpool/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ import (
"testing"

"github.com/holiman/uint256"
"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/firehose"
)

// Tests that transactions can be added to strict lists and list contents and
Expand Down Expand Up @@ -78,3 +83,63 @@ func BenchmarkListAdd(b *testing.B) {
}
}
}

func TestFilterTxConditional(t *testing.T) {
t.Parallel()

// Create an in memory state db to test against.
memDb := rawdb.NewMemoryDatabase()
db := state.NewDatabase(memDb)
state, _ := state.New(common.Hash{}, db, nil)

// Create a private key to sign transactions.
key, _ := crypto.GenerateKey()

// Create a list.
list := newList(true)

// Create a transaction with no defined tx options
// and add to the list.
tx := transaction(0, 1000, key)
list.Add(tx, DefaultConfig.PriceBump)

// There should be no drops at this point.
// No state has been modified.
drops := list.FilterTxConditional(state)

count := len(drops)
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)

// Create another transaction with a known account storage root tx option
// and add to the list.
tx2 := transaction(1, 1000, key)

var options types.OptionsAA4337

options.KnownAccounts = types.KnownAccounts{
common.Address{19: 1}: &types.Value{
Single: common.HexToRefHash("0xe734938daf39aae1fa4ee64dc3155d7c049f28b57a8ada8ad9e86832e0253bef"),
},
}

state.SetState(common.Address{19: 1}, common.Hash{}, common.Hash{30: 1}, firehose.NoOpContext)
tx2.PutOptions(&options)
list.Add(tx2, DefaultConfig.PriceBump)

// There should still be no drops as no state has been modified.
drops = list.FilterTxConditional(state)

count = len(drops)
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)

// Set state that conflicts with tx2's policy
state.SetState(common.Address{19: 1}, common.Hash{}, common.Hash{31: 1}, firehose.NoOpContext)

// tx2 should be the single transaction filtered out
drops = list.FilterTxConditional(state)

count = len(drops)
require.Equal(t, 1, count, "got %d filtered by TxOptions when there should be a single one", count)

require.Equal(t, tx2, drops[0], "Got %x, expected %x", drops[0].Hash(), tx2.Hash())
}
13 changes: 11 additions & 2 deletions core/txpool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -2314,10 +2314,19 @@ func (pool *TxPool) demoteUnexecutables() {
pool.enqueueTx(hash, tx, false, false)
}

pendingGauge.Dec(int64(oldsLen + dropsLen + invalidsLen))
// Drop all transactions that no longer have valid TxOptions
txConditionalsRemoved := list.FilterTxConditional(pool.currentState)

for _, tx := range txConditionalsRemoved {
hash := tx.Hash()
pool.all.Remove(hash)
log.Trace("Removed invalid conditional transaction", "hash", hash)
}

pendingGauge.Dec(int64(oldsLen + dropsLen + invalidsLen + len(txConditionalsRemoved)))

if pool.locals.contains(addr) {
localGauge.Dec(int64(oldsLen + dropsLen + invalidsLen))
localGauge.Dec(int64(oldsLen + dropsLen + invalidsLen + len(txConditionalsRemoved)))
}
// If there's a gap in front, alert (should never happen) and postpone all transactions
if list.Len() > 0 && list.txs.Get(nonce) == nil {
Expand Down
4 changes: 4 additions & 0 deletions core/txpool/txpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,7 @@ func TestUnderpricing(t *testing.T) {
keys[i], _ = crypto.GenerateKey()
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
}

// Generate and queue a batch of transactions, both pending and queued
txs := types.Transactions{}

Expand Down Expand Up @@ -2024,6 +2025,7 @@ func TestUnderpricing(t *testing.T) {
if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}

// Ensure that adding an underpriced transaction on block limit fails
if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); !errors.Is(err, ErrUnderpriced) {
t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
Expand Down Expand Up @@ -2065,6 +2067,7 @@ func TestUnderpricing(t *testing.T) {
if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}

// Ensure that adding local transactions can push out even higher priced ones
ltx = pricedTransaction(1, 100000, big.NewInt(0), keys[2])
if err := pool.AddLocal(ltx); err != nil {
Expand Down Expand Up @@ -2264,6 +2267,7 @@ func TestUnderpricingDynamicFee(t *testing.T) {
if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}

// Ensure that adding local transactions can push out even higher priced ones
ltx = dynamicFeeTx(1, 100000, big.NewInt(0), big.NewInt(0), keys[2])
if err := pool.AddLocal(ltx); err != nil {
Expand Down
38 changes: 38 additions & 0 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,44 @@ func (h *Header) EmptyReceipts() bool {
return h.ReceiptHash == EmptyReceiptsHash
}

// ValidateBlockNumberOptions4337 validates the block range passed as in the options parameter in the conditional transaction (EIP-4337)
func (h *Header) ValidateBlockNumberOptions4337(minBlockNumber *big.Int, maxBlockNumber *big.Int) error {
currentBlockNumber := h.Number

if minBlockNumber != nil {
if currentBlockNumber.Cmp(minBlockNumber) == -1 {
return fmt.Errorf("current block number %v is less than minimum block number: %v", currentBlockNumber, minBlockNumber)
}
}

if maxBlockNumber != nil {
if currentBlockNumber.Cmp(maxBlockNumber) == 1 {
return fmt.Errorf("current block number %v is greater than maximum block number: %v", currentBlockNumber, maxBlockNumber)
}
}

return nil
}

// ValidateBlockNumberOptions4337 validates the timestamp range passed as in the options parameter in the conditional transaction (EIP-4337)
func (h *Header) ValidateTimestampOptions4337(minTimestamp *uint64, maxTimestamp *uint64) error {
currentBlockTime := h.Time

if minTimestamp != nil {
if currentBlockTime < *minTimestamp {
return fmt.Errorf("current block time %v is less than minimum timestamp: %v", currentBlockTime, minTimestamp)
}
}

if maxTimestamp != nil {
if currentBlockTime > *maxTimestamp {
return fmt.Errorf("current block time %v is greater than maximum timestamp: %v", currentBlockTime, maxTimestamp)
}
}

return nil
}

// Body is a simple (mutable, non-safe) data container for storing and moving
// a block's data contents (transactions and uncles) together.
type Body struct {
Expand Down
Loading

0 comments on commit 2486d3e

Please sign in to comment.