Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra state reports #1287

Merged
merged 23 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c831476
Feat: submit state reports to remote chains
dwasse Aug 28, 2023
14600b1
Feat: add SubmitStateReportWithAttestation on LightInbox
dwasse Aug 28, 2023
ff7c99f
WIP: verify number of reports on agent domain
dwasse Aug 28, 2023
6d8a10d
Feat: add prepareStateReport() for all report submissions
dwasse Aug 28, 2023
b55451b
Feat: add working state report verification to TestReportFraudulentSt…
dwasse Aug 29, 2023
37f3f1b
Feat: add verifyStateReport() helper
dwasse Aug 29, 2023
84f57af
Feat: add verifyStateReport() helper
dwasse Aug 29, 2023
c5c6780
WIP: add RelayableAgentStatus model
dwasse Aug 29, 2023
5996a4f
Cleanup: remove unused dispute handling
dwasse Aug 29, 2023
4b29978
WIP: working TestFraudulentStateInSnapshot with new agent status model
dwasse Aug 29, 2023
01d40d5
WIP: fix crosstable logic, logs
dwasse Aug 30, 2023
1a727eb
Feat: add NotaryOnDestination to test setup
dwasse Aug 30, 2023
3685aa0
WIP: working test with NotaryOnDestination and Order clause in db query
dwasse Aug 30, 2023
397c10c
Cleanup: logs, dead code
dwasse Aug 30, 2023
2c4688f
Fix: db tests
dwasse Aug 30, 2023
f2dc74e
Cleanup: lints
dwasse Aug 30, 2023
9ee450a
Cleanup: remove Debug() gorm flags
dwasse Aug 30, 2023
80de403
Feat: add updateAgentStatus() test helper
dwasse Aug 30, 2023
2251f4e
Cleanup: update db comment
dwasse Aug 30, 2023
5148cf2
Cleanup: correct db comment
dwasse Aug 30, 2023
77e7eba
Fix: some lints
dwasse Aug 30, 2023
c9cc789
Cleanup: lint
dwasse Aug 30, 2023
67eee66
Cleanup: clear nonce
dwasse Aug 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions agents/agents/guard/db/agent_root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ func (t *DBSuite) TestGetSummitBlockNumberForRoot() {
Nil(t.T(), err)

// Call GetSummitBlockNumberForRoot for each agent root.
blockNumber, err := testDB.GetSummitBlockNumberForRoot(t.GetTestContext(), agentRootA)
blockNumber, err := testDB.GetSummitBlockNumberForRoot(t.GetTestContext(), agentRootA.String())
Nil(t.T(), err)
Equal(t.T(), blockNumberA, blockNumber)

blockNumber, err = testDB.GetSummitBlockNumberForRoot(t.GetTestContext(), agentRootB)
blockNumber, err = testDB.GetSummitBlockNumberForRoot(t.GetTestContext(), agentRootB.String())
Nil(t.T(), err)
Equal(t.T(), blockNumberB, blockNumber)
})
Expand Down
37 changes: 17 additions & 20 deletions agents/agents/guard/db/crosstable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ import (
"github.com/synapsecns/sanguine/agents/types"
)

func (t *DBSuite) TestGetUpdateAgentStatusParameters() {
func (t *DBSuite) TestGetRelayableAgentStatuses() {
t.RunOnAllDBs(func(testDB db.GuardDB) {
guardAddress := common.BigToAddress(big.NewInt(gofakeit.Int64()))

addressA := common.BigToAddress(big.NewInt(gofakeit.Int64()))
addressB := common.BigToAddress(big.NewInt(gofakeit.Int64()))
addressC := common.BigToAddress(big.NewInt(gofakeit.Int64()))
Expand Down Expand Up @@ -48,37 +46,36 @@ func (t *DBSuite) TestGetUpdateAgentStatusParameters() {
)
Nil(t.T(), err)

// Insert three rows into `Dispute`, two will have matching agent address to `AgentTree` rows and with status `Resolved`.
err = testDB.StoreDispute(
// Insert three rows into `RelayableAgentStatus`, two will have matching agent address to `AgentTree` rows and with status `Queued`.
chainA := gofakeit.Uint32()
chainB := chainA + 1
err = testDB.StoreRelayableAgentStatus(
t.GetTestContext(),
big.NewInt(gofakeit.Int64()),
types.Resolved,
guardAddress,
gofakeit.Uint32(),
addressA,
types.AgentFlagUnknown,
types.AgentFlagActive,
chainA,
)
Nil(t.T(), err)
err = testDB.StoreDispute(
err = testDB.StoreRelayableAgentStatus(
t.GetTestContext(),
big.NewInt(gofakeit.Int64()),
types.Resolved,
guardAddress,
gofakeit.Uint32(),
addressB,
types.AgentFlagUnknown,
types.AgentFlagActive,
chainA,
)
Nil(t.T(), err)
err = testDB.StoreDispute(
err = testDB.StoreRelayableAgentStatus(
t.GetTestContext(),
big.NewInt(gofakeit.Int64()),
types.Opened,
guardAddress,
gofakeit.Uint32(),
addressC,
types.AgentFlagUnknown,
types.AgentFlagActive,
chainB,
)
Nil(t.T(), err)

// Get the matching agent tree from the database.
agentTrees, err := testDB.GetUpdateAgentStatusParameters(t.GetTestContext())
agentTrees, err := testDB.GetRelayableAgentStatuses(t.GetTestContext(), chainA)
Nil(t.T(), err)

Equal(t.T(), 2, len(agentTrees))
Expand Down
29 changes: 13 additions & 16 deletions agents/agents/guard/db/guard_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package db

import (
"context"
"math/big"

"github.com/ethereum/go-ethereum/common"
agentTypes "github.com/synapsecns/sanguine/agents/types"
Expand All @@ -11,22 +10,20 @@ import (

// GuardDBWriter is the interface for writing to the guard's database.
type GuardDBWriter interface {
// StoreDispute stores a dispute.
StoreDispute(
// StoreRelayableAgentStatus stores a relayable agent status.
StoreRelayableAgentStatus(
ctx context.Context,
disputeIndex *big.Int,
disputeProcessedStatus agentTypes.DisputeProcessedStatus,
guardAddress common.Address,
notaryIndex uint32,
notaryAddress common.Address,
agentAddress common.Address,
staleFlag agentTypes.AgentFlagType,
updatedFlag agentTypes.AgentFlagType,
domain uint32,
) error

// UpdateDisputeProcessedStatus updates the DisputedProcessedStatus for a dispute.
UpdateDisputeProcessedStatus(
// UpdateAgentStatusRelayedState updates the relayed state for a relayable agent status.
UpdateAgentStatusRelayedState(
ctx context.Context,
guardAddress *common.Address,
notaryAddress *common.Address,
flag agentTypes.DisputeProcessedStatus,
agentAddress common.Address,
state agentTypes.AgentStatusRelayedState,
) error

// StoreAgentTree stores an agent tree.
Expand All @@ -48,10 +45,10 @@ type GuardDBWriter interface {

// GuardDBReader is the interface for reading from the guard's database.
type GuardDBReader interface {
// GetUpdateAgentStatusParameters gets eligible parameters for the updateAgentStatus() contract call.
GetUpdateAgentStatusParameters(ctx context.Context) ([]agentTypes.AgentTree, error)
// GetRelayableAgentStatuses gets eligible parameters for the updateAgentStatus() contract call.
GetRelayableAgentStatuses(ctx context.Context, chainID uint32) ([]agentTypes.AgentTree, error)
// GetSummitBlockNumberForRoot gets the summit block number for a given agent root.
GetSummitBlockNumberForRoot(ctx context.Context, agentRoot [32]byte) (uint64, error)
GetSummitBlockNumberForRoot(ctx context.Context, agentRoot string) (uint64, error)
}

// GuardDB is the interface for the guard's database.
Expand Down
7 changes: 3 additions & 4 deletions agents/agents/guard/db/sql/base/agent_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ func (s Store) StoreAgentRoot(
}

// GetSummitBlockNumberForRoot gets the summit block number for a given agent root.
func (s Store) GetSummitBlockNumberForRoot(ctx context.Context, agentRoot [32]byte) (uint64, error) {
dbAgentRoot := common.BytesToHash(agentRoot[:]).String()

func (s Store) GetSummitBlockNumberForRoot(ctx context.Context, agentRoot string) (uint64, error) {
var blockNumber uint64
dbTx := s.DB().WithContext(ctx).
Where(fmt.Sprintf("%s = ?", AgentRootFieldName), dbAgentRoot).
Where(fmt.Sprintf("%s = ?", AgentRootFieldName), agentRoot).
Order(fmt.Sprintf("%s ASC", BlockNumberFieldName)).
Limit(1).
Model(&AgentRoot{}).
Pluck(BlockNumberFieldName, &blockNumber)
dwasse marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
2 changes: 1 addition & 1 deletion agents/agents/guard/db/sql/base/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (s Store) SubmitterDB() submitterDB.Service {
// GetAllModels gets all models to migrate.
// see: https://medium.com/@SaifAbid/slice-interfaces-8c78f8b6345d for an explanation of why we can't do this at initialization time
func GetAllModels() (allModels []interface{}) {
allModels = append(allModels, &Dispute{}, &AgentTree{}, &AgentRoot{})
allModels = append(allModels, &RelayableAgentStatus{}, &AgentTree{}, &AgentRoot{})
allModels = append(allModels, txdb.GetAllModels()...)
return allModels
}
57 changes: 35 additions & 22 deletions agents/agents/guard/db/sql/base/crosstable.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,53 @@ import (
"github.com/synapsecns/sanguine/core/dbcommon"
)

// GetUpdateAgentStatusParameters gets the parameters for updating the agent status with the following steps:
// 1. Outer join the `AgentTree` table on the `Dispute` table on the `NotaryAddress` <-> `AgentAddress` fields.
// 2. Filter the rows where the `DisputeProcessedStatus` is `Resolved`.
// 3. Return each of remaining rows' `AgentRoot`, `AgentAddress`, and `Proof` fields.
func (s Store) GetUpdateAgentStatusParameters(ctx context.Context) ([]agentTypes.AgentTree, error) {
type agentTreeWithStatus struct {
AgentTree
AgentDomain uint32
UpdatedAgentFlag agentTypes.AgentFlagType
}

// GetRelayableAgentStatuses gets the parameters for updating the agent status with the following steps:
// 1. Load the `AgentTree` table.
// 2. Filter the rows where the `AgentStatusRelayedState` is `Queued`, and the `Domain` is the given `chainID`.
// 3. Outer join the `AgentTree` table on the `RelayableAgentStatus` table on the `AgentAddress` fields.
// 4. Return all fields in the `AgentTree` table as well as `UpdatedFlag` from the `RelayableAgentStatus` table.
func (s Store) GetRelayableAgentStatuses(ctx context.Context, chainID uint32) ([]agentTypes.AgentTree, error) {
agentTreesTableName, err := dbcommon.GetModelName(s.DB(), &AgentTree{})
if err != nil {
return nil, fmt.Errorf("failed to get agent trees table name: %w", err)
}

disputesTableName, err := dbcommon.GetModelName(s.DB(), &Dispute{})
relayableAgentStatusesTableName, err := dbcommon.GetModelName(s.DB(), &RelayableAgentStatus{})
if err != nil {
return nil, fmt.Errorf("failed to get disputes table name: %w", err)
return nil, fmt.Errorf("failed to get relayable agent statuses table name: %w", err)
}

query, err := interpol.WithMap(
`
SELECT * FROM {agentTreesTable} AS aTable
SELECT aTable.*, rTable.{updatedFlag}
FROM {agentTreesTable} AS aTable
JOIN (
SELECT * FROM {disputesTable} WHERE {disputeProcessedStatus} = ?
) AS dTable
ON aTable.{agentAddress} = dTable.{notaryAddress}
SELECT * FROM {relayableAgentStatusesTable}
WHERE {agentStatusRelayedState} = ?
AND {domain} = ?
) AS rTable
ON aTable.{agentAddress} = rTable.{agentAddress}
`,
map[string]string{
"agentTreesTable": agentTreesTableName,
"disputesTable": disputesTableName,
"agentAddress": AgentAddressFieldName,
"notaryAddress": NotaryAddressFieldName,
"disputeProcessedStatus": DisputeProcessedStatusFieldName,
"domain": DomainFieldName,
"updatedFlag": UpdatedFlagFieldName,
"agentTreesTable": agentTreesTableName,
"relayableAgentStatusesTable": relayableAgentStatusesTableName,
"agentStatusRelayedState": AgentStatusRelayedStateFieldName,
"agentAddress": AgentAddressFieldName,
})
if err != nil {
return nil, fmt.Errorf("failed to interpolate query: %w", err)
}

var dbAgentTrees []AgentTree
err = s.DB().WithContext(ctx).Raw(query, agentTypes.Resolved).Scan(&dbAgentTrees).Error
var dbAgentTrees []agentTreeWithStatus
err = s.DB().WithContext(ctx).Raw(query, agentTypes.Queued, chainID).Scan(&dbAgentTrees).Error
if err != nil {
return nil, fmt.Errorf("failed to get agent trees: %w", err)
}
Expand All @@ -60,10 +71,12 @@ func (s Store) GetUpdateAgentStatusParameters(ctx context.Context) ([]agentTypes
return nil, fmt.Errorf("could not unmarshal proof: %w", err)
}
agentTrees = append(agentTrees, agentTypes.AgentTree{
AgentRoot: tree.AgentRoot,
AgentAddress: common.HexToAddress(tree.AgentAddress),
BlockNumber: tree.BlockNumber,
Proof: proofBytes,
AgentRoot: tree.AgentRoot,
AgentAddress: common.HexToAddress(tree.AgentAddress),
AgentDomain: chainID,
UpdatedAgentFlag: tree.UpdatedAgentFlag,
BlockNumber: tree.BlockNumber,
Proof: proofBytes,
})
}
return agentTrees, nil
Expand Down
71 changes: 0 additions & 71 deletions agents/agents/guard/db/sql/base/dispute.go

This file was deleted.

42 changes: 21 additions & 21 deletions agents/agents/guard/db/sql/base/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,40 @@ import (
func init() {
namer := dbcommon.NewNamer(GetAllModels())
AgentRootFieldName = namer.GetConsistentName("AgentRoot")
DisputeIndexFieldName = namer.GetConsistentName("DisputeIndex")
AgentAddressFieldName = namer.GetConsistentName("AgentAddress")
BlockNumberFieldName = namer.GetConsistentName("BlockNumber")
DisputeProcessedStatusFieldName = namer.GetConsistentName("DisputeProcessedStatus")
NotaryAddressFieldName = namer.GetConsistentName("NotaryAddress")
AgentStatusRelayedStateFieldName = namer.GetConsistentName("AgentStatusRelayedState")
DomainFieldName = namer.GetConsistentName("Domain")
UpdatedFlagFieldName = namer.GetConsistentName("UpdatedFlag")
}

var (
// AgentRootFieldName is the field name of the agent root.
AgentRootFieldName string
// DisputeIndexFieldName is the field name of the agent root.
DisputeIndexFieldName string
// AgentAddressFieldName gets the agent address field name.
AgentAddressFieldName string
// BlockNumberFieldName gets the agent block number field name.
BlockNumberFieldName string
// DisputeProcessedStatusFieldName gets the dispute processed status field name.
DisputeProcessedStatusFieldName string
// NotaryAddressFieldName gets the notary address field name.
NotaryAddressFieldName string
// AgentStatusRelayedStateFieldName gets the relayable agent status field name.
AgentStatusRelayedStateFieldName string
// DomainFieldName gets the agent domain field name.
DomainFieldName string
// UpdatedFlagFieldName gets the updated flag field name.
UpdatedFlagFieldName string
)

// Dispute is a dispute between two agents.
type Dispute struct {
// DisputeIndex is the index of the dispute on the BondingManager.
DisputeIndex uint64 `gorm:"column:dispute_index;primaryKey"`
// DisputeProcessedStatus indicates the status of the dispute.
DisputeProcessedStatus agentTypes.DisputeProcessedStatus `gorm:"column:dispute_processed_status"`
// GuardAddress is the address of the guard.
GuardAddress string `gorm:"column:guard_address"`
// NotaryIndex is the index of the notary on the BondingManager.
NotaryIndex uint64 `gorm:"column:notary_index"`
// NotaryAddress is the address of the notary.
NotaryAddress string `gorm:"column:notary_address"`
// RelayableAgentStatus is used for tracking agent statuses that are out of
// sync and need to be relayed to a remote chain.
type RelayableAgentStatus struct {
AgentAddress string `gorm:"column:agent_address"`
// StaleFlag is the old flag that needs to be updated.
StaleFlag agentTypes.AgentFlagType `gorm:"column:stale_flag"`
// UpdatedFlag is the new flag value that should be relayed.
UpdatedFlag agentTypes.AgentFlagType `gorm:"column:updated_flag"`
// Domain is the domain of the agent status.
Domain uint32 `gorm:"column:domain"`
// AgentStatusRelayedState is the state of the relayable agent status.
AgentStatusRelayedState agentTypes.AgentStatusRelayedState `gorm:"column:agent_status_relayed_state"`
}

// AgentTree is the state of an agent tree on Summit.
Expand Down
Loading
Loading