Skip to content

Commit

Permalink
Merge branch 'master' into backfill_blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
abi87 committed Oct 26, 2023
2 parents 6e8d83b + 3a0283f commit 61819ed
Show file tree
Hide file tree
Showing 19 changed files with 184 additions and 207 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.20

require (
github.com/VictoriaMetrics/fastcache v1.10.0
github.com/ava-labs/avalanchego v1.10.12-0.20231005190735-e911af925f6c
github.com/ava-labs/avalanchego v1.10.12-rc.5
github.com/cespare/cp v0.1.0
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811
github.com/davecgh/go-spew v1.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/ava-labs/avalanchego v1.10.12-0.20231005190735-e911af925f6c h1:8V65SWrP+IsMLwECc+2vN+3SIKzLFFz/y3PZ7erG5so=
github.com/ava-labs/avalanchego v1.10.12-0.20231005190735-e911af925f6c/go.mod h1:SrcFAwibYWdUnS7ZRbENDBzQgHYCROuX6w/lhGmJcPo=
github.com/ava-labs/avalanchego v1.10.12-rc.5 h1:lOljTUF59rZ/SKlTSZ3XQwuy4uGVNikHIEMQmYHzws4=
github.com/ava-labs/avalanchego v1.10.12-rc.5/go.mod h1:SrcFAwibYWdUnS7ZRbENDBzQgHYCROuX6w/lhGmJcPo=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down
4 changes: 3 additions & 1 deletion params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,9 @@ type ChainConfig struct {
BanffBlockTimestamp *uint64 `json:"banffBlockTimestamp,omitempty"`
// Cortina increases the block gas limit to 15M. (nil = no fork, 0 = already activated)
CortinaBlockTimestamp *uint64 `json:"cortinaBlockTimestamp,omitempty"`
// DUpgrade activates the Shanghai upgrade from Ethereum. (nil = no fork, 0 = already activated)
// DUpgrade activates the Shanghai Execution Spec Upgrade from Ethereum (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md#included-eips)
// and Avalanche Warp Messaging. (nil = no fork, 0 = already activated)
// Note: EIP-4895 is excluded since withdrawals are not relevant to the Avalanche C-Chain or Subnets running the EVM.
DUpgradeBlockTimestamp *uint64 `json:"dUpgradeBlockTimestamp,omitempty"`
// Cancun activates the Cancun upgrade from Ethereum. (nil = no fork, 0 = already activated)
CancunTime *uint64 `json:"cancunTime,omitempty"`
Expand Down
16 changes: 16 additions & 0 deletions plugin/evm/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,39 @@ func NewAdminService(vm *VM, performanceDir string) *Admin {
func (p *Admin) StartCPUProfiler(_ *http.Request, _ *struct{}, _ *api.EmptyReply) error {
log.Info("Admin: StartCPUProfiler called")

p.vm.ctx.Lock.Lock()
defer p.vm.ctx.Lock.Unlock()

return p.profiler.StartCPUProfiler()
}

// StopCPUProfiler stops the cpu profile
func (p *Admin) StopCPUProfiler(r *http.Request, _ *struct{}, _ *api.EmptyReply) error {
log.Info("Admin: StopCPUProfiler called")

p.vm.ctx.Lock.Lock()
defer p.vm.ctx.Lock.Unlock()

return p.profiler.StopCPUProfiler()
}

// MemoryProfile runs a memory profile writing to the specified file
func (p *Admin) MemoryProfile(_ *http.Request, _ *struct{}, _ *api.EmptyReply) error {
log.Info("Admin: MemoryProfile called")

p.vm.ctx.Lock.Lock()
defer p.vm.ctx.Lock.Unlock()

return p.profiler.MemoryProfile()
}

// LockProfile runs a mutex profile writing to the specified file
func (p *Admin) LockProfile(_ *http.Request, _ *struct{}, _ *api.EmptyReply) error {
log.Info("Admin: LockProfile called")

p.vm.ctx.Lock.Lock()
defer p.vm.ctx.Lock.Unlock()

return p.profiler.LockProfile()
}

Expand All @@ -59,6 +71,10 @@ type SetLogLevelArgs struct {

func (p *Admin) SetLogLevel(_ *http.Request, args *SetLogLevelArgs, reply *api.EmptyReply) error {
log.Info("EVM: SetLogLevel called", "logLevel", args.Level)

p.vm.ctx.Lock.Lock()
defer p.vm.ctx.Lock.Unlock()

if err := p.vm.logger.SetLogLevel(args.Level); err != nil {
return fmt.Errorf("failed to parse log level: %w ", err)
}
Expand Down
2 changes: 1 addition & 1 deletion plugin/evm/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func (b *Block) Reject(context.Context) error {
log.Debug(fmt.Sprintf("Rejecting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height()))
for _, tx := range b.atomicTxs {
b.vm.mempool.RemoveTx(tx)
if err := b.vm.issueTx(tx, false /* set local to false when re-issuing */); err != nil {
if err := b.vm.mempool.AddTx(tx); err != nil {
log.Debug("Failed to re-issue transaction in rejected block", "txID", tx.ID(), "err", err)
}
}
Expand Down
8 changes: 4 additions & 4 deletions plugin/evm/export_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func createExportTxOptions(t *testing.T, vm *VM, issuer chan engCommon.Message,
t.Fatal(err)
}

if err := vm.issueTx(importTx, true /*=local*/); err != nil {
if err := vm.mempool.AddLocalTx(importTx); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -371,7 +371,7 @@ func TestExportTxEVMStateTransfer(t *testing.T) {
t.Fatal(err)
}

if err := vm.issueTx(tx, true /*=local*/); err != nil {
if err := vm.mempool.AddLocalTx(tx); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -1726,7 +1726,7 @@ func TestNewExportTx(t *testing.T) {
t.Fatal(err)
}

if err := vm.issueTx(tx, true /*=local*/); err != nil {
if err := vm.mempool.AddLocalTx(tx); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -1916,7 +1916,7 @@ func TestNewExportTxMulticoin(t *testing.T) {
t.Fatal(err)
}

if err := vm.issueTx(tx, false); err != nil {
if err := vm.mempool.AddTx(tx); err != nil {
t.Fatal(err)
}

Expand Down
2 changes: 1 addition & 1 deletion plugin/evm/gossip_mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestAtomicMempoolIterate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)
m, err := NewMempool(ids.Empty, 10)
m, err := NewMempool(ids.Empty, 10, nil)
require.NoError(err)

for _, add := range tt.add {
Expand Down
2 changes: 1 addition & 1 deletion plugin/evm/gossiper.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ func (h *GossipHandler) HandleAtomicTx(nodeID ids.NodeID, msg message.AtomicTxGo
}

h.stats.IncAtomicGossipReceivedNew()
if err := h.vm.issueTx(&tx, false /*=local*/); err != nil {
if err := h.vm.mempool.AddTx(&tx); err != nil {
log.Trace(
"AppGossip provided invalid transaction",
"peerID", nodeID,
Expand Down
4 changes: 2 additions & 2 deletions plugin/evm/gossiper_atomic_gossiping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestMempoolAtmTxsIssueTxAndGossiping(t *testing.T) {
assert.NoError(vm.SetState(context.Background(), snow.NormalOp))

// Optimistically gossip raw tx
assert.NoError(vm.issueTx(tx, true /*=local*/))
assert.NoError(vm.mempool.AddLocalTx(tx))
time.Sleep(500 * time.Millisecond)
gossipedLock.Lock()
assert.Equal(1, gossiped)
Expand All @@ -74,7 +74,7 @@ func TestMempoolAtmTxsIssueTxAndGossiping(t *testing.T) {
gossipedLock.Unlock()

// Attempt to gossip conflicting tx
assert.ErrorIs(vm.issueTx(conflictingTx, true /*=local*/), errConflictingAtomicTx)
assert.ErrorIs(vm.mempool.AddLocalTx(conflictingTx), errConflictingAtomicTx)
gossipedLock.Lock()
assert.Equal(1, gossiped)
gossipedLock.Unlock()
Expand Down
28 changes: 27 additions & 1 deletion plugin/evm/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ type Mempool struct {
bloom *gossip.BloomFilter

metrics *mempoolMetrics

verify func(tx *Tx) error
}

// NewMempool returns a Mempool with [maxSize]
func NewMempool(AVAXAssetID ids.ID, maxSize int) (*Mempool, error) {
func NewMempool(AVAXAssetID ids.ID, maxSize int, verify func(tx *Tx) error) (*Mempool, error) {
bloom, err := gossip.NewBloomFilter(txGossipBloomMaxItems, txGossipBloomFalsePositiveRate)
if err != nil {
return nil, fmt.Errorf("failed to initialize bloom filter: %w", err)
Expand All @@ -95,6 +97,7 @@ func NewMempool(AVAXAssetID ids.ID, maxSize int) (*Mempool, error) {
utxoSpenders: make(map[ids.ID]*Tx),
bloom: bloom,
metrics: newMempoolMetrics(),
verify: verify,
}, nil
}

Expand Down Expand Up @@ -145,6 +148,24 @@ func (m *Mempool) AddTx(tx *Tx) error {
m.lock.Lock()
defer m.lock.Unlock()

err := m.addTx(tx, false)
if err != nil {
// unlike local txs, invalid remote txs are recorded as discarded
// so that they won't be requested again
txID := tx.ID()
m.discardedTxs.Put(tx.ID(), tx)
log.Debug("failed to issue remote tx to mempool",
"txID", txID,
"err", err,
)
}
return err
}

func (m *Mempool) AddLocalTx(tx *Tx) error {
m.lock.Lock()
defer m.lock.Unlock()

return m.addTx(tx, false)
}

Expand Down Expand Up @@ -203,6 +224,11 @@ func (m *Mempool) addTx(tx *Tx, force bool) error {
if _, exists := m.txHeap.Get(txID); exists {
return nil
}
if !force && m.verify != nil {
if err := m.verify(tx); err != nil {
return err
}
}

utxoSet := tx.InputUTXOs()
gasPrice, _ := m.atomicTxGasPrice(tx)
Expand Down
94 changes: 22 additions & 72 deletions plugin/evm/mempool_atomic_gossiping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@ package evm

import (
"context"
"math/big"
"testing"

"github.com/ava-labs/coreth/params"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
"github.com/ava-labs/avalanchego/vms/components/avax"
"github.com/ava-labs/avalanchego/vms/components/chain"
"github.com/ava-labs/avalanchego/vms/secp256k1fx"

"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -49,13 +45,13 @@ func TestMempoolAddLocallyCreateAtomicTx(t *testing.T) {
conflictingTxID := conflictingTx.ID()

// add a tx to the mempool
err := vm.issueTx(tx, true /*=local*/)
err := vm.mempool.AddLocalTx(tx)
assert.NoError(err)
has := mempool.has(txID)
assert.True(has, "valid tx not recorded into mempool")

// try to add a conflicting tx
err = vm.issueTx(conflictingTx, true /*=local*/)
err = vm.mempool.AddLocalTx(conflictingTx)
assert.ErrorIs(err, errConflictingAtomicTx)
has = mempool.has(conflictingTxID)
assert.False(has, "conflicting tx in mempool")
Expand Down Expand Up @@ -118,88 +114,42 @@ func TestMempoolMaxMempoolSizeHandling(t *testing.T) {
assert.True(mempool.has(tx.ID()))
}

func createImportTx(t *testing.T, vm *VM, txID ids.ID, feeAmount uint64) *Tx {
var importAmount uint64 = 10000000
importTx := &UnsignedImportTx{
NetworkID: testNetworkID,
BlockchainID: testCChainID,
SourceChain: testXChainID,
ImportedInputs: []*avax.TransferableInput{
{
UTXOID: avax.UTXOID{
TxID: txID,
OutputIndex: uint32(0),
},
Asset: avax.Asset{ID: testAvaxAssetID},
In: &secp256k1fx.TransferInput{
Amt: importAmount,
Input: secp256k1fx.Input{
SigIndices: []uint32{0},
},
},
},
{
UTXOID: avax.UTXOID{
TxID: txID,
OutputIndex: uint32(1),
},
Asset: avax.Asset{ID: testAvaxAssetID},
In: &secp256k1fx.TransferInput{
Amt: importAmount,
Input: secp256k1fx.Input{
SigIndices: []uint32{0},
},
},
},
},
Outs: []EVMOutput{
{
Address: testEthAddrs[0],
Amount: importAmount - feeAmount,
AssetID: testAvaxAssetID,
},
{
Address: testEthAddrs[1],
Amount: importAmount,
AssetID: testAvaxAssetID,
},
},
}

// Sort the inputs and outputs to ensure the transaction is canonical
utils.Sort(importTx.ImportedInputs)
utils.Sort(importTx.Outs)

tx := &Tx{UnsignedAtomicTx: importTx}
// Sign with the correct key
if err := tx.Sign(vm.codec, [][]*secp256k1.PrivateKey{{testKeys[0]}}); err != nil {
t.Fatal(err)
}

return tx
}

// mempool will drop transaction with the lowest fee
func TestMempoolPriorityDrop(t *testing.T) {
assert := assert.New(t)

// we use AP3 genesis here to not trip any block fees
_, vm, _, _, _ := GenesisVM(t, true, genesisJSONApricotPhase3, "", "")
importAmount := uint64(50000000)
_, vm, _, _, _ := GenesisVMWithUTXOs(t, true, genesisJSONApricotPhase3, "", "", map[ids.ShortID]uint64{
testShortIDAddrs[0]: importAmount,
testShortIDAddrs[1]: importAmount,
})
defer func() {
err := vm.Shutdown(context.Background())
assert.NoError(err)
}()
mempool := vm.mempool
mempool.maxSize = 1

tx1 := createImportTx(t, vm, ids.ID{1}, params.AvalancheAtomicTxFee)
tx1, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]})
if err != nil {
t.Fatal(err)
}
assert.NoError(mempool.AddTx(tx1))
assert.True(mempool.has(tx1.ID()))
tx2 := createImportTx(t, vm, ids.ID{2}, params.AvalancheAtomicTxFee)

tx2, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[1], initialBaseFee, []*secp256k1.PrivateKey{testKeys[1]})
if err != nil {
t.Fatal(err)
}
assert.ErrorIs(mempool.AddTx(tx2), errInsufficientAtomicTxFee)
assert.True(mempool.has(tx1.ID()))
assert.False(mempool.has(tx2.ID()))
tx3 := createImportTx(t, vm, ids.ID{3}, 2*params.AvalancheAtomicTxFee)

tx3, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[1], new(big.Int).Mul(initialBaseFee, big.NewInt(2)), []*secp256k1.PrivateKey{testKeys[1]})
if err != nil {
t.Fatal(err)
}
assert.NoError(mempool.AddTx(tx3))
assert.False(mempool.has(tx1.ID()))
assert.False(mempool.has(tx2.ID()))
Expand Down
2 changes: 1 addition & 1 deletion plugin/evm/mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

func TestMempoolAddTx(t *testing.T) {
require := require.New(t)
m, err := NewMempool(ids.Empty, 5_000)
m, err := NewMempool(ids.Empty, 5_000, nil)
require.NoError(err)

txs := make([]*GossipAtomicTx, 0)
Expand Down
Loading

0 comments on commit 61819ed

Please sign in to comment.