Skip to content

Commit

Permalink
Only use anvil for tests that require increaseTime() cheatcode (#1590)
Browse files Browse the repository at this point in the history
* Fix: add SetupBackends() helper

* Cleanup: temp disable tests that require anvil

* Fix: remove unnecessary test condition

* Cleanup: go mod tidy

* WIP: add back anvil tests, add GetChainTimeFunc to executor

* Fix: TestUpdateAgentStatusOnRemote

* Fix: build

* Fix: remove AnvilGuardSuite, add shouldUseAnvil()

* Fix: do getProof() in submitTransaction func

* Fix: only do completeSlashing() for nonzero domain

* Cleanup: remove logs

* Try doing TestUpdateAgentStatusOnRemote last

* Add test teardown

* Use ptr receiver on test suites

* Cleanup: remove logs

* Bump timeout for test suite

* Cleanup: remove log

* make tidy

---------

Co-authored-by: Trajan0x <[email protected]>
  • Loading branch information
dwasse and trajan0x authored Dec 12, 2023
1 parent a5aac41 commit 281439a
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 95 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ jobs:
retries=0
while [ $retries -lt $max_num_retries ]; do
if $PYROSCOPE_PATH exec --apiKey=${{ secrets.PYROSCOPE_CLOUD_TOKEN }} -- gotestsum --rerun-fails=3 --packages="$pkg" --format standard-verbose -- -v -coverpkg="$pkg" -coverprofile=profile.cov $pkg; then
if $PYROSCOPE_PATH exec --apiKey=${{ secrets.PYROSCOPE_CLOUD_TOKEN }} -- gotestsum --rerun-fails=3 --packages="$pkg" --format standard-verbose -- -v -timeout 30m -coverpkg="$pkg" -coverprofile=profile.cov $pkg; then
break
else
retries=$((retries+1))
Expand Down
67 changes: 43 additions & 24 deletions agents/agents/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ type Executor struct {
retryConfig []retry.WithBackoffConfigurator
// NowFunc returns the current time.
NowFunc func() time.Time
// GetChainTimeFunc gets the chain time.
GetChainTimeFunc func(ctx context.Context, backend Backend) (uint64, error)
}

// logOrderInfo is a struct to keep track of the order of a log.
Expand Down Expand Up @@ -240,16 +242,17 @@ func NewExecutor(ctx context.Context, config executor.Config, executorDB db.Exec
}

return &Executor{
config: config,
executorDB: executorDB,
grpcConn: conn,
grpcClient: grpcClient,
signer: executorSigner,
chainExecutors: chainExecutors,
handler: handler,
txSubmitter: txSubmitter,
retryConfig: retryConfig,
NowFunc: time.Now,
config: config,
executorDB: executorDB,
grpcConn: conn,
grpcClient: grpcClient,
signer: executorSigner,
chainExecutors: chainExecutors,
handler: handler,
txSubmitter: txSubmitter,
retryConfig: retryConfig,
NowFunc: time.Now,
GetChainTimeFunc: getChainTime,
}, nil
}

Expand Down Expand Up @@ -325,6 +328,7 @@ func (e Executor) Execute(parentCtx context.Context, message types.Message) (_ b
ctx, span := e.handler.Tracer().Start(parentCtx, "Execute", trace.WithAttributes(
attribute.Int(metrics.Origin, int(originDomain)),
attribute.Int(metrics.Destination, int(destinationDomain)),
attribute.Int("message_type", int(message.Header().Flag())),
))

defer func() {
Expand Down Expand Up @@ -560,35 +564,50 @@ func (e Executor) verifyMessageOptimisticPeriod(parentCtx context.Context, messa
return nil, nil
}

var currentTime uint64
chainCall := func(ctx context.Context) error {
var err error
latestHeader, err := e.chainExecutors[chainID].rpcClient.HeaderByNumber(ctx, nil)
var chainTime uint64
call := func(ctx context.Context) error {
chainTime, err = e.GetChainTimeFunc(ctx, e.chainExecutors[chainID].rpcClient)
if err != nil {
return fmt.Errorf("could not get latest header: %w", err)
}

if latestHeader == nil {
return fmt.Errorf("latest header is nil")
return fmt.Errorf("could not get chain time: %w", err)
}

currentTime = latestHeader.Time

return nil
}
err = retry.WithBackoff(ctx, chainCall, e.retryConfig...)
err = retry.WithBackoff(ctx, call, e.retryConfig...)
if err != nil {
return nil, fmt.Errorf("could not get latest header: %w", err)
}

if *messageMinimumTime > currentTime {
span.AddEvent("got current time", trace.WithAttributes(
attribute.Int("chain_time", int(chainTime)),
))

if *messageMinimumTime > chainTime {
span.AddEvent("message is not old enough", trace.WithAttributes(
attribute.Int("message_minimum_time", int(*messageMinimumTime)),
attribute.Int("chain_time", int(chainTime)),
))
//nolint:nilnil
return nil, nil
}

return &nonce, nil
}

func getChainTime(ctx context.Context, backend Backend) (uint64, error) {
var chainTime uint64
latestHeader, err := backend.HeaderByNumber(ctx, nil)
if err != nil {
return chainTime, fmt.Errorf("could not get latest header: %w", err)
}

if latestHeader == nil {
return chainTime, fmt.Errorf("latest header is nil")
}

chainTime = latestHeader.Time
return chainTime, nil
}

// newTreeFromDB creates a new merkle tree from the database's messages.
func newTreeFromDB(ctx context.Context, chainID uint32, executorDB db.ExecutorDB) (*merkle.HistoricalTree, error) {
var allMessages []types.Message
Expand Down
11 changes: 3 additions & 8 deletions agents/agents/executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,14 +626,6 @@ func (e *ExecutorSuite) TestExecutor() {
err = e.ExecutorTestDB.StoreAttestation(e.GetTestContext(), destinationAttestation, destination, 1, 1)
e.Nil(err)

mask := execTypes.DBMessage{
ChainID: &chainID,
Destination: &destination,
}
executableMessages, err := e.ExecutorTestDB.GetExecutableMessages(e.GetTestContext(), mask, uint64(time.Now().Unix()), 1)
e.Nil(err)
e.Len(executableMessages, 0)

// Make sure there is one executable message in the database.
e.Eventually(func() bool {
mask := execTypes.DBMessage{
Expand Down Expand Up @@ -797,6 +789,9 @@ func (e *ExecutorSuite) TestSetMinimumTime() {

//nolint:maintidx
func (e *ExecutorSuite) TestSendManagerMessage() {
// This test requires a call to anvil's evm.IncreaseTime() cheat code, so we should
// set up the backends with anvil.

testDone := false
defer func() {
testDone = true
Expand Down
29 changes: 17 additions & 12 deletions agents/agents/guard/fraud.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,21 +334,26 @@ func (g Guard) handleStatusUpdated(ctx context.Context, log ethTypes.Log, chainI
//nolint:exhaustive
switch types.AgentFlagType(statusUpdated.Flag) {
case types.AgentFlagFraudulent:
var agentProof [][32]byte
contractCall := func(ctx context.Context) error {
agentProof, err = g.domains[g.summitDomainID].BondingManager().GetProof(ctx, statusUpdated.Agent)
if err != nil {
return fmt.Errorf("could not get proof: %w", err)
}

// Only perform completeSlashing for notary fraud.
if statusUpdated.Domain == 0 {
return nil
}
err = retry.WithBackoff(ctx, contractCall, g.retryConfig...)
if err != nil {
return fmt.Errorf("could not get proof: %w", err)
}

// Submit completeSlashing() tx after fetching agent proof.
_, err = g.txSubmitter.SubmitTransaction(ctx, big.NewInt(int64(g.summitDomainID)), func(transactor *bind.TransactOpts) (tx *ethTypes.Transaction, err error) {
var agentProof [][32]byte
contractCall := func(ctx context.Context) error {
agentProof, err = g.domains[g.summitDomainID].BondingManager().GetProof(ctx, statusUpdated.Agent)
if err != nil {
return fmt.Errorf("could not get proof: %w", err)
}

return nil
}
err = retry.WithBackoff(ctx, contractCall, g.retryConfig...)
if err != nil {
return nil, fmt.Errorf("could not get proof: %w", err)
}
tx, err = g.domains[g.summitDomainID].BondingManager().CompleteSlashing(
transactor,
statusUpdated.Domain,
Expand All @@ -362,7 +367,7 @@ func (g Guard) handleStatusUpdated(ctx context.Context, log ethTypes.Log, chainI
return
})
if err != nil {
return fmt.Errorf("could not submit CompleteSlashing tx: %w", err)
return fmt.Errorf("could not submit completeSlashing tx: %w", err)
}
case types.AgentFlagSlashed:
var agentRoot [32]byte
Expand Down
30 changes: 20 additions & 10 deletions agents/agents/guard/fraud_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package guard_test

import (
"context"
"fmt"
"math/big"
"time"
Expand Down Expand Up @@ -31,7 +32,7 @@ import (
"github.com/synapsecns/sanguine/services/scribe/service"
)

func (g GuardSuite) getTestGuard(scribeConfig scribeConfig.Config) (testGuard *guard.Guard, sclient client.ScribeClient, err error) {
func (g *GuardSuite) getTestGuard(scribeConfig scribeConfig.Config) (testGuard *guard.Guard, sclient client.ScribeClient, err error) {
testConfig := config.AgentConfig{
Domains: map[string]config.DomainConfig{
"origin_client": g.OriginDomainClient.Config(),
Expand Down Expand Up @@ -87,7 +88,7 @@ func (g GuardSuite) getTestGuard(scribeConfig scribeConfig.Config) (testGuard *g
return testGuard, sclient, nil
}

func (g GuardSuite) bumpBackends() {
func (g *GuardSuite) bumpBackends() {
txContextSummit := g.TestBackendSummit.GetTxContext(g.GetTestContext(), g.SummitMetadata.OwnerPtr())
txContextOrigin := g.TestBackendOrigin.GetTxContext(g.GetTestContext(), g.OriginContractMetadata.OwnerPtr())
txContextDestination := g.TestBackendDestination.GetTxContext(g.GetTestContext(), g.DestinationContractMetadata.OwnerPtr())
Expand All @@ -97,13 +98,13 @@ func (g GuardSuite) bumpBackends() {
}

// Helper to get the test backend to emit expected events.
func (g GuardSuite) bumpBackend(backend backends.SimulatedTestBackend, contract *agentstestcontract.AgentsTestContractRef, txOpts *bind.TransactOpts) {
func (g *GuardSuite) bumpBackend(backend backends.SimulatedTestBackend, contract *agentstestcontract.AgentsTestContractRef, txOpts *bind.TransactOpts) {
bumpTx, err := contract.EmitAgentsEventA(txOpts, big.NewInt(gofakeit.Int64()), big.NewInt(gofakeit.Int64()), big.NewInt(gofakeit.Int64()))
Nil(g.T(), err)
backend.WaitForConfirmation(g.GetTestContext(), bumpTx)
}

func (g GuardSuite) updateAgentStatus(lightManager domains.LightManagerContract, bondedSigner, unbondedSigner signer.Signer, chainID uint32) {
func (g *GuardSuite) updateAgentStatus(lightManager domains.LightManagerContract, bondedSigner, unbondedSigner signer.Signer, chainID uint32) {
agentStatus, err := g.SummitDomainClient.BondingManager().GetAgentStatus(g.GetTestContext(), bondedSigner.Address())
Nil(g.T(), err)
agentProof, err := g.SummitDomainClient.BondingManager().GetProof(g.GetTestContext(), bondedSigner.Address())
Expand All @@ -121,7 +122,7 @@ func (g GuardSuite) updateAgentStatus(lightManager domains.LightManagerContract,
}

// TODO: Add a test for exiting the report logic early when the snapshot submitter is a guard.
func (g GuardSuite) TestFraudulentStateInSnapshot() {
func (g *GuardSuite) TestFraudulentStateInSnapshot() {
testDone := false
defer func() {
testDone = true
Expand Down Expand Up @@ -257,7 +258,7 @@ func (g GuardSuite) TestFraudulentStateInSnapshot() {
g.verifyStateReport(g.LightInboxOnDestination, 1, fraudulentState)
}

func (g GuardSuite) TestFraudulentAttestationOnDestination() {
func (g *GuardSuite) TestFraudulentAttestationOnDestination() {
testDone := false
defer func() {
testDone = true
Expand Down Expand Up @@ -380,7 +381,7 @@ func (g GuardSuite) TestFraudulentAttestationOnDestination() {
})
}

func (g GuardSuite) TestReportFraudulentStateInAttestation() {
func (g *GuardSuite) TestReportFraudulentStateInAttestation() {
testDone := false
defer func() {
testDone = true
Expand Down Expand Up @@ -521,7 +522,7 @@ type statementInboxContract interface {
// Verify that a state report was submitted on the given contract.
//
//nolint:unparam
func (g GuardSuite) verifyStateReport(contract statementInboxContract, expectedNumReports int64, expectedState types.State) {
func (g *GuardSuite) verifyStateReport(contract statementInboxContract, expectedNumReports int64, expectedState types.State) {
g.Eventually(func() bool {
numReports, err := contract.GetReportsAmount(&bind.CallOpts{Context: g.GetTestContext()})
Nil(g.T(), err)
Expand All @@ -543,7 +544,7 @@ func (g GuardSuite) verifyStateReport(contract statementInboxContract, expectedN
})
}

func (g GuardSuite) TestInvalidReceipt() {
func (g *GuardSuite) TestInvalidReceipt() {
testDone := false
defer func() {
testDone = true
Expand Down Expand Up @@ -720,7 +721,10 @@ func (g GuardSuite) TestInvalidReceipt() {
}

//nolint:maintidx,cyclop
func (g GuardSuite) TestUpdateAgentStatusOnRemote() {
func (g *GuardSuite) TestUpdateAgentStatusOnRemote() {
// This test requires a call to anvil's evm.IncreaseTime() cheat code, so we should
// set up the backends with anvil.

testDone := false
defer func() {
testDone = true
Expand Down Expand Up @@ -838,11 +842,15 @@ func (g GuardSuite) TestUpdateAgentStatusOnRemote() {
}
return *currentTime
}
getChainTimeFunc := func(ctx context.Context, backend executor.Backend) (uint64, error) {
return uint64(nowFunc().Unix()), nil
}

// Start a new Executor.
exec, err := executor.NewExecutor(g.GetTestContext(), excCfg, g.ExecutorTestDB, scribeClient, omniRPCClient, g.ExecutorMetrics)
Nil(g.T(), err)
exec.NowFunc = nowFunc
exec.GetChainTimeFunc = getChainTimeFunc

go func() {
execErr := exec.Run(g.GetTestContext())
Expand Down Expand Up @@ -1024,6 +1032,8 @@ func (g GuardSuite) TestUpdateAgentStatusOnRemote() {
Nil(g.T(), err)
err = anvilClient.IncreaseTime(g.GetTestContext(), seconds)
Nil(g.T(), err)
err = anvilClient.Mine(g.GetTestContext(), 1)
Nil(g.T(), err)
}
increaseEvmTime(g.TestBackendSummit, optimisticPeriodSeconds+offset)
g.bumpBackends()
Expand Down
8 changes: 8 additions & 0 deletions agents/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,16 @@ require (

require (
dario.cat/mergo v1.0.0 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect
github.com/influxdata/influxdb v1.8.3 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.5.1 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/peterh/liner v1.2.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect
)

require (
Expand Down
5 changes: 5 additions & 0 deletions agents/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0=
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk=
Expand Down Expand Up @@ -736,6 +737,7 @@ github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vA
github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI=
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
github.com/influxdata/influxdb-client-go/v2 v2.5.1 h1:ytMbX2YeupSsec1Exp3zALTjvfhXkvxcyV6nOXkjG3s=
github.com/influxdata/influxdb-client-go/v2 v2.5.1/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU=
github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk=
github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE=
Expand Down Expand Up @@ -797,6 +799,7 @@ github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
Expand Down Expand Up @@ -1023,6 +1026,7 @@ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNc
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/peterh/liner v1.2.1 h1:O4BlKaq/LWu6VRWmol4ByWfzx6MfXc5Op5HETyIy5yg=
github.com/peterh/liner v1.2.1/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
Expand Down Expand Up @@ -1180,6 +1184,7 @@ github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiu
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.0.0-20191119114148-6dd40a46baa0/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
Loading

0 comments on commit 281439a

Please sign in to comment.