Skip to content

Commit

Permalink
feat: make blocktracker aware of block hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
fbac committed Jan 8, 2025
1 parent 3356985 commit 03a7564
Show file tree
Hide file tree
Showing 18 changed files with 234 additions and 94 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ __debug_*
build/
bin/

# contracts development config
contracts/config/anvil_localnet/

# Test binary, built with `go test -c`
*.test

Expand Down
8 changes: 4 additions & 4 deletions contracts/config/anvil_localnet/GroupMessages.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"addresses": {
"groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"groupMessagesImpl": "0xc5a5C42992dECbae36851359345FE25997F5C42d",
"groupMessagesProxy": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
"groupMessagesImpl": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"groupMessagesProxy": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
},
"deploymentBlock": 28,
"latestUpgradeBlock": 28
"deploymentBlock": 0,
"latestUpgradeBlock": 0
}
8 changes: 4 additions & 4 deletions contracts/config/anvil_localnet/IdentityUpdates.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"addresses": {
"identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"identityUpdatesImpl": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
"identityUpdatesProxy": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
"identityUpdatesImpl": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
"identityUpdatesProxy": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
},
"deploymentBlock": 30,
"latestUpgradeBlock": 30
"deploymentBlock": 2,
"latestUpgradeBlock": 2
}
4 changes: 2 additions & 2 deletions pkg/blockchain/registryAdmin.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ func (n *NodeRegistryAdmin) AddNode(
httpAddress string,
) error {
if !common.IsHexAddress(owner) {
return fmt.Errorf("Invalid owner address provided %s", owner)
return fmt.Errorf("invalid owner address provided %s", owner)
}

ownerAddress := common.HexToAddress(owner)
signingKey := crypto.FromECDSAPub(signingKeyPub)

if n.signer == nil {
return fmt.Errorf("No signer provided")
return fmt.Errorf("no signer provided")
}
tx, err := n.contract.AddNode(&bind.TransactOpts{
Context: ctx,
Expand Down
4 changes: 2 additions & 2 deletions pkg/blockchain/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func NewPrivateKeySigner(privateKeyString string, chainID int) (*PrivateKeySigne
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
return nil, fmt.Errorf("Failed to cast to ECDSA public key %v", err)
return nil, fmt.Errorf("failed to cast to ECDSA public key %v", err)
}

fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
Expand All @@ -42,7 +42,7 @@ func NewPrivateKeySigner(privateKeyString string, chainID int) (*PrivateKeySigne
big.NewInt(int64(chainID)),
)
if err != nil {
return nil, fmt.Errorf("Failed to create transactor: %v", err)
return nil, fmt.Errorf("failed to create transactor: %v", err)
}

return &PrivateKeySigner{
Expand Down
9 changes: 5 additions & 4 deletions pkg/db/queries.sql
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,18 @@ WHERE
originator_node_id = @originator_node_id;

-- name: SetLatestBlock :exec
INSERT INTO latest_block(contract_address, block_number)
VALUES (@contract_address, @block_number)
INSERT INTO latest_block(contract_address, block_number, block_hash)
VALUES (@contract_address, @block_number, @block_hash)
ON CONFLICT (contract_address)
DO UPDATE SET
block_number = @block_number
block_number = @block_number, block_hash = @block_hash
WHERE
@block_number > latest_block.block_number;

-- name: GetLatestBlock :one
SELECT
block_number
block_number,
block_hash
FROM
latest_block
WHERE
Expand Down
1 change: 1 addition & 0 deletions pkg/db/queries/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 16 additions & 9 deletions pkg/db/queries/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 48 additions & 17 deletions pkg/indexer/blockTracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sync"
"sync/atomic"

"github.com/ethereum/go-ethereum/common"
"github.com/xmtp/xmtpd/pkg/db/queries"
)

Expand All @@ -18,12 +19,17 @@ and allows the user to increase the value.
*
*/
type BlockTracker struct {
latestBlock atomic.Uint64
latestBlock *Block
contractAddress string
queries *queries.Queries
mu sync.Mutex
}

type Block struct {
number atomic.Uint64
hash common.Hash
}

// Return a new BlockTracker initialized to the latest block from the DB
func NewBlockTracker(
ctx context.Context,
Expand All @@ -39,64 +45,89 @@ func NewBlockTracker(
if err != nil {
return nil, err
}
bt.latestBlock.Store(latestBlock)
bt.latestBlock = latestBlock

return bt, nil
}

func (bt *BlockTracker) GetLatestBlock() uint64 {
return bt.latestBlock.Load()
func (bt *BlockTracker) GetLatestBlockNumber() uint64 {
return bt.latestBlock.number.Load()
}

func (bt *BlockTracker) UpdateLatestBlock(ctx context.Context, block uint64) error {
func (bt *BlockTracker) GetLatestBlockHash() common.Hash {
bt.mu.Lock()
defer bt.mu.Unlock()
return bt.latestBlock.hash
}

func (bt *BlockTracker) UpdateLatestBlock(
ctx context.Context,
block uint64,
hash common.Hash,
) error {
// Quick check without lock
if block <= bt.latestBlock.Load() {
if block <= bt.latestBlock.number.Load() {
return nil
}

bt.mu.Lock()
defer bt.mu.Unlock()

// Re-check after acquiring lock
if block <= bt.latestBlock.Load() {
if block <= bt.latestBlock.number.Load() {
return nil
}

if err := bt.updateDB(ctx, block); err != nil {
if err := bt.updateDB(ctx, block, hash); err != nil {
return err
}

bt.latestBlock.Store(block)
if hash == (common.Hash{}) {
return fmt.Errorf("invalid block hash %s", hash.String())
}

bt.latestBlock.number.Store(block)
bt.latestBlock.hash = hash

return nil
}

func (bt *BlockTracker) updateDB(ctx context.Context, block uint64) error {
func (bt *BlockTracker) updateDB(ctx context.Context, block uint64, hash common.Hash) error {
return bt.queries.SetLatestBlock(ctx, queries.SetLatestBlockParams{
ContractAddress: bt.contractAddress,
BlockNumber: int64(block),
BlockHash: hash.Bytes(),
})
}

func loadLatestBlock(
ctx context.Context,
contractAddress string,
querier *queries.Queries,
) (uint64, error) {
) (*Block, error) {
block := &Block{
number: atomic.Uint64{},
hash: common.Hash{},
}

latestBlock, err := querier.GetLatestBlock(ctx, contractAddress)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return 0, nil
return block, nil
}
return 0, err
return block, err
}

if latestBlock < 0 {
return 0, fmt.Errorf(
if latestBlock.BlockNumber < 0 {
return block, fmt.Errorf(
"invalid block number %d for contract %s",
latestBlock,
latestBlock.BlockNumber,
contractAddress,
)
}

return uint64(latestBlock), nil
block.number.Store(uint64(latestBlock.BlockNumber))
block.hash = common.BytesToHash(latestBlock.BlockHash)

return block, nil
}
Loading

0 comments on commit 03a7564

Please sign in to comment.