diff --git a/apps/randomness/monitor-randomness.ts b/apps/randomness/monitor-randomness.ts index 96c242cb2f..65a8211bd0 100644 --- a/apps/randomness/monitor-randomness.ts +++ b/apps/randomness/monitor-randomness.ts @@ -5,6 +5,7 @@ import { z } from "zod" const RANDOMNESS_CONTRACT_ABI = abis.Random const RANDOMNESS_CONTRACT_ADDRESS = deployment.Random + const DRAND_SERVICE_URL = "https://api.drand.sh/v2/beacons/evmnet" const client = createPublicClient({ diff --git a/contracts/deployments/anvil/random/abis.json b/contracts/deployments/anvil/random/abis.json index dae6b8ec37..9b66bad5fb 100644 --- a/contracts/deployments/anvil/random/abis.json +++ b/contracts/deployments/anvil/random/abis.json @@ -114,6 +114,7 @@ "name": "drandPK0", "inputs": [], "outputs": [ + { "name": "", "type": "uint256", diff --git a/contracts/src/randomness/Drand.sol b/contracts/src/randomness/Drand.sol index aba53f83bc..77c2910a5f 100644 --- a/contracts/src/randomness/Drand.sol +++ b/contracts/src/randomness/Drand.sol @@ -46,6 +46,7 @@ contract Drand { mstore(add(0x20, hashedRoundBytes), hashedRound) } uint256[2] memory message = BLS.hashToPoint(DST, hashedRoundBytes); + // NB: Always check that the signature is a valid signature (a valid G1 point on the curve)! if (!BLS.isValidSignature(signature)) { revert InvalidSignature([DRAND_PK_0, DRAND_PK_1, DRAND_PK_2, DRAND_PK_3], message, signature); diff --git a/packages/txm/lib/BlockMonitor.ts b/packages/txm/lib/BlockMonitor.ts index 6aeace90de..804436b8c9 100644 --- a/packages/txm/lib/BlockMonitor.ts +++ b/packages/txm/lib/BlockMonitor.ts @@ -17,9 +17,16 @@ export class BlockMonitor { constructor(_transactionManager: TransactionManager) { this.txmgr = _transactionManager + } + async start() { this.txmgr.viemClient.watchBlocks({ onBlock: this.onNewBlock.bind(this), + ...(this.txmgr.transportProtocol === "http" + ? { + pollingInterval: this.txmgr.pollingInterval, + } + : {}), }) } diff --git a/packages/txm/lib/TransactionManager.ts b/packages/txm/lib/TransactionManager.ts index 25915a3d18..29c583a145 100644 --- a/packages/txm/lib/TransactionManager.ts +++ b/packages/txm/lib/TransactionManager.ts @@ -63,6 +63,12 @@ export type TransactionManagerConfig = { * Defaults to false. */ allowDebug?: boolean + + /** + * Specifies the polling interval in milliseconds. + * Defaults to 1/2 of the block time. + */ + pollingInterval?: number } /** The private key of the account used for signing transactions. */ privateKey: Hex @@ -159,6 +165,8 @@ export class TransactionManager { public readonly rpcAllowDebug: boolean public readonly blockTime: bigint public readonly finalizedTransactionPurgeTime: number + public readonly pollingInterval: number + public readonly transportProtocol: "http" | "websocket" constructor(_config: TransactionManagerConfig) { this.collectors = [] @@ -169,12 +177,14 @@ export class TransactionManager { throw protocol.error } + this.transportProtocol = protocol.value + const retries = _config.rpc.retries || 2 const retryDelay = _config.rpc.retryDelay || 50 const timeout = _config.rpc.timeout || 500 let transport: ViemTransport - if (protocol.value === "http") { + if (this.transportProtocol === "http") { transport = viemHttpTransport(_config.rpc.url, { timeout, retryCount: retries, @@ -247,6 +257,8 @@ export class TransactionManager { this.rpcAllowDebug = _config.rpc.allowDebug || false this.blockTime = _config.blockTime || 2n this.finalizedTransactionPurgeTime = _config.finalizedTransactionPurgeTime || 2 * 60 * 1000 + + this.pollingInterval = _config.rpc.pollingInterval || (Number(this.blockTime) * 1000) / 2 } /** @@ -309,7 +321,10 @@ export class TransactionManager { throw new Error(errorMessage) } - // Await the completion of the gas price oracle startup before marking the TransactionManager as started + // Wait for the gas price oracle to initialize before starting the block monitor, + // which emits 'NewBlock' events as the TXM heartbeat. await priceOraclePromise + + await this.blockMonitor.start() } }