Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -188,21 +188,6 @@ describe('railgun-smart-wallet', function runTests() {
};
});

it('Should fail to instantiate without a polling provider', () => {
const nonPollingProvider = new JsonRpcProvider(config.rpc);
expect(() => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
return new RailgunSmartWalletContract(
'abc',
nonPollingProvider as any,
nonPollingProvider as any,
chain,
);
}).to.throw(
'The JsonRpcProvider must have polling enabled. Use PollingJsonRpcProvider to instantiate.',
);
});

it('[HH] Should retrieve merkle root from contract', async function run() {
if (!isDefined(process.env.RUN_HARDHAT_TESTS)) {
this.skip();
Expand Down
29 changes: 12 additions & 17 deletions src/contracts/railgun-smart-wallet/V2/railgun-smart-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import {
Contract,
ContractEventPayload,
ContractTransaction,
FallbackProvider,
Interface,
JsonRpcApiProvider,
Provider,
Result,
} from 'ethers';
import EventEmitter from 'events';
Expand Down Expand Up @@ -62,8 +63,6 @@ const SCAN_TIMEOUT_ERROR_MESSAGE = 'getLogs request timed out after 5 seconds.';
export class RailgunSmartWalletContract extends EventEmitter {
readonly contract: RailgunSmartWallet;

readonly contractForListeners: RailgunSmartWallet;

readonly address: string;

readonly chain: Chain;
Expand All @@ -73,12 +72,18 @@ export class RailgunSmartWalletContract extends EventEmitter {
/**
* Connect to Railgun instance on network
* @param railgunSmartWalletContractAddress - address of Railgun instance (Proxy contract)
* @param provider - Network provider
* @param defaultProvider - Network provider
* @param pollingProvider - DEPRECATED
* @param chain
*/
constructor(
railgunSmartWalletContractAddress: string,
defaultProvider: PollingJsonRpcProvider | FallbackProvider,
pollingProvider: PollingJsonRpcProvider,
defaultProvider: Provider,
/**
* @deprecated pollingProvider will be removed in the next major version.
*/
pollingProvider?: Provider,
// @ts-ignore - Ignore optional param last requirement during deprecation
chain: Chain,
) {
super();
Expand All @@ -89,15 +94,6 @@ export class RailgunSmartWalletContract extends EventEmitter {
defaultProvider,
) as unknown as RailgunSmartWallet;

// Because of a 'stallTimeout' bug in Ethers v6, all providers in a FallbackProvider will get called simultaneously.
// So, we'll use a single json rpc (the first in the FallbackProvider) to poll for the event listeners.
assertIsPollingProvider(pollingProvider);
this.contractForListeners = new Contract(
railgunSmartWalletContractAddress,
ABIRailgunSmartWallet,
pollingProvider,
) as unknown as RailgunSmartWallet;

this.chain = chain;
}

Expand Down Expand Up @@ -290,7 +286,7 @@ export class RailgunSmartWalletContract extends EventEmitter {
const transactTopic = this.contract.getEvent('Transact').getFragment().topicHash;
const unshieldTopic = this.contract.getEvent('Unshield').getFragment().topicHash;

await this.contractForListeners.on(
await this.contract.on(
// @ts-expect-error - Use * to request all events
'*', // All Events
(event: ContractEventPayload) => {
Expand Down Expand Up @@ -633,6 +629,5 @@ export class RailgunSmartWalletContract extends EventEmitter {
*/
async unload() {
await this.contract.removeAllListeners();
await this.contractForListeners?.removeAllListeners();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Contract, ContractEventPayload, FallbackProvider, Result } from 'ethers';
import { Contract, ContractEventPayload, Provider, Result } from 'ethers';
import EventEmitter from 'events';
import { Chain } from '../../../models/engine-types';
import { PollingJsonRpcProvider } from '../../../provider/polling-json-rpc-provider';
import { PoseidonMerkleAccumulator } from '../../../abi/typechain/PoseidonMerkleAccumulator';
import { ABIPoseidonMerkleAccumulator } from '../../../abi/abi';
import { ByteLength, ByteUtils } from '../../../utils/bytes';
import EngineDebug from '../../../debugger/debugger';
import { assertIsPollingProvider } from '../../../provider/polling-util';
import {
EngineEvent,
EventsCommitmentListener,
Expand All @@ -29,8 +27,6 @@ const SCAN_TIMEOUT_ERROR_MESSAGE = 'getLogs request timed out after 5 seconds.';
export class PoseidonMerkleAccumulatorContract extends EventEmitter {
readonly contract: PoseidonMerkleAccumulator;

readonly contractForListeners: PoseidonMerkleAccumulator;

readonly address: string;

readonly chain: Chain;
Expand All @@ -39,10 +35,20 @@ export class PoseidonMerkleAccumulatorContract extends EventEmitter {

private readonly eventTopic: string;

/**
* @param address
* @param provider
* @param pollingProvider - DEPRECATED
* @param chain
*/
constructor(
address: string,
provider: PollingJsonRpcProvider | FallbackProvider,
pollingProvider: PollingJsonRpcProvider,
provider: Provider,
/**
* @deprecated pollingProvider will be removed in the next major version.
*/
pollingProvider?: Provider,
// @ts-ignore - Ignore optional param last requirement during deprecation
chain: Chain,
) {
super();
Expand All @@ -54,15 +60,6 @@ export class PoseidonMerkleAccumulatorContract extends EventEmitter {
) as unknown as PoseidonMerkleAccumulator;
this.eventTopic = this.contract.getEvent('AccumulatorStateUpdate').getFragment().topicHash;
this.chain = chain;

// Because of a 'stallTimeout' bug in Ethers v6, all providers in a FallbackProvider will get called simultaneously.
// So, we'll use a single json rpc (the first in the FallbackProvider) to poll for the event listeners.
assertIsPollingProvider(pollingProvider);
this.contractForListeners = new Contract(
address,
ABIPoseidonMerkleAccumulator,
pollingProvider,
) as unknown as PoseidonMerkleAccumulator;
}

/**
Expand Down Expand Up @@ -104,7 +101,7 @@ export class PoseidonMerkleAccumulatorContract extends EventEmitter {
eventsRailgunTransactionsV3Listener: EventsRailgunTransactionListenerV3,
triggerWalletBalanceDecryptions: (txidVersion: TXIDVersion) => Promise<void>,
): Promise<void> {
await this.contractForListeners.on(this.eventTopic as any, (event: ContractEventPayload) => {
await this.contract.on(this.eventTopic as any, (event: ContractEventPayload) => {
try {
if (event.log.topics.length !== 1) {
throw new Error('Requires one topic for railgun events');
Expand Down Expand Up @@ -264,6 +261,5 @@ export class PoseidonMerkleAccumulatorContract extends EventEmitter {
*/
async unload() {
await this.contract.removeAllListeners();
await this.contractForListeners?.removeAllListeners();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Contract, ContractTransaction, FallbackProvider } from 'ethers';
import { PollingJsonRpcProvider } from '../../../provider/polling-json-rpc-provider';
import { Contract, ContractTransaction, Provider } from 'ethers';
import { PoseidonMerkleVerifier } from '../../../abi/typechain/PoseidonMerkleVerifier';
import { ABIPoseidonMerkleVerifier } from '../../../abi/abi';
import { ShieldCiphertextStruct } from '../../../abi/typechain/RailgunSmartWallet';
Expand All @@ -9,7 +8,7 @@ export class PoseidonMerkleVerifierContract {

readonly address: string;

constructor(address: string, provider: PollingJsonRpcProvider | FallbackProvider) {
constructor(address: string, provider: Provider) {
this.address = address;
this.contract = new Contract(
address,
Expand Down
5 changes: 2 additions & 3 deletions src/contracts/railgun-smart-wallet/V3/token-vault-contract.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Contract, FallbackProvider } from 'ethers';
import { Contract, Provider } from 'ethers';
import { TokenDataStructOutput, TokenVault } from '../../../abi/typechain/TokenVault';
import { PollingJsonRpcProvider } from '../../../provider/polling-json-rpc-provider';
import { ABITokenVault } from '../../../abi/abi';
import { ByteLength, ByteUtils } from '../../../utils/bytes';
import EngineDebug from '../../../debugger/debugger';
Expand All @@ -10,7 +9,7 @@ export class TokenVaultContract {

readonly address: string;

constructor(address: string, provider: PollingJsonRpcProvider | FallbackProvider) {
constructor(address: string, provider: Provider) {
this.address = address;
this.contract = new Contract(address, ABITokenVault, provider) as unknown as TokenVault;
}
Expand Down
43 changes: 17 additions & 26 deletions src/railgun-engine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { AbstractLevelDOWN } from 'abstract-leveldown';
import EventEmitter from 'events';
import { FallbackProvider } from 'ethers';
import type { JsonRpcApiProvider, Provider } from 'ethers';
import { RailgunSmartWalletContract } from './contracts/railgun-smart-wallet/V2/railgun-smart-wallet';
import { RelayAdaptV2Contract } from './contracts/relay-adapt/V2/relay-adapt-v2';
import { Database, DatabaseNamespace } from './database/database';
Expand Down Expand Up @@ -46,8 +46,6 @@ import {
CURRENT_TXID_V2_MERKLETREE_HISTORY_VERSION,
CURRENT_UTXO_MERKLETREE_HISTORY_VERSION,
} from './utils/constants';
import { PollingJsonRpcProvider } from './provider/polling-json-rpc-provider';
import { assertIsPollingProvider } from './provider/polling-util';
import { isDefined } from './utils/is-defined';
import { UTXOMerkletree } from './merkletree/utxo-merkletree';
import { TXIDMerkletree } from './merkletree/txid-merkletree';
Expand Down Expand Up @@ -1445,20 +1443,31 @@ class RailgunEngine extends EventEmitter {

/**
* Load network
* @param chain
* @param railgunSmartWalletContractAddress - address of railgun instance (proxy contract)
* @param relayAdaptV2ContractAddress - address of railgun instance (proxy contract)
* @param provider - ethers provider for network
* @param deploymentBlock - block number to start scanning from
*/
* @param poseidonMerkleAccumulatorV3Address
* @param poseidonMerkleVerifierV3Address
* @param tokenVaultV3Address
* @param defaultProvider - ethers provider for network
* @param pollingProvider - DEPRECATED
* @param deploymentBlocks - block number to start scanning from
* @param poiLaunchBlock
* @param supportsV3
*/
async loadNetwork(
chain: Chain,
railgunSmartWalletContractAddress: string,
relayAdaptV2ContractAddress: string,
poseidonMerkleAccumulatorV3Address: string,
poseidonMerkleVerifierV3Address: string,
tokenVaultV3Address: string,
defaultProvider: PollingJsonRpcProvider | FallbackProvider,
pollingProvider: PollingJsonRpcProvider,
defaultProvider: Provider,
/**
* @deprecated pollingProvider will be removed in the next major version.
*/
pollingProvider?: Provider,
// @ts-ignore - Ignore optional param last requirement during deprecation
deploymentBlocks: Record<TXIDVersion, number>,
poiLaunchBlock: Optional<number>,
supportsV3: boolean,
Expand All @@ -1480,24 +1489,6 @@ class RailgunEngine extends EventEmitter {
throw err;
}

assertIsPollingProvider(pollingProvider);
try {
await promiseTimeout(
pollingProvider.getBlockNumber(),
60_000,
'Timed out waiting for polling RPC provider to connect.',
);
} catch (cause) {
const err = new Error(
'Failed to get block number from polling provider when loading network',
{
cause,
},
);
EngineDebug.error(cause as Error);
throw err;
}

if (supportsV3) {
addChainSupportsV3(chain);
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export const awaitRailgunSmartWalletEvent = async (
new Promise<void>((resolve) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
// @ts-expect-error
RailgunVersionedSmartContracts.getAccumulator(txidVersion, chain).contractForListeners.once(
RailgunVersionedSmartContracts.getAccumulator(txidVersion, chain).contract.once(
event,
() => resolve(),
);
Expand Down
Loading