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
76 changes: 65 additions & 11 deletions packages/cli/src/scripts/settlement/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import "reflect-metadata";
import { container } from "tsyringe";
import type { Environment } from "@proto-kit/stack";

import {
loadEnvironmentVariables,
Expand All @@ -11,14 +10,28 @@ import { loadUserModules } from "../../utils/loadUserModules";

export default async function (options: LoadEnvOptions) {
try {
const { Provable, PublicKey } = await import("o1js");
loadEnvironmentVariables(options);
const { Provable, PublicKey, PrivateKey } = await import("o1js");
const { Runtime } = await import("@proto-kit/module");
const { Protocol } = await import("@proto-kit/protocol");
const { AppChain, Sequencer, SettlementModule, InMemoryDatabase } =
await import("@proto-kit/sequencer");
const {
AppChain,
Sequencer,
SettlementModule,
InMemoryDatabase,
BatchProducerModule,
BridgingModule,
ConstantFeeStrategy,
InMemoryMinaSigner,
MinaBaseLayer,
PrivateMempool,
LocalTaskQueue,
LocalTaskWorkerModule,
VanillaTaskWorkerModules,
SequencerStartupModule,
} = await import("@proto-kit/sequencer");

const { DefaultModules, DefaultConfigs } = await import("@proto-kit/stack");
loadEnvironmentVariables(options);
const { DefaultConfigs } = await import("@proto-kit/stack");
const { runtime, protocol } = await loadUserModules();
const appChain = AppChain.from({
Runtime: Runtime.from(runtime.modules),
Expand All @@ -28,7 +41,18 @@ export default async function (options: LoadEnvOptions) {
}),
Sequencer: Sequencer.from({
Database: InMemoryDatabase,
...DefaultModules.settlementScript(),
BaseLayer: MinaBaseLayer,
FeeStrategy: ConstantFeeStrategy,
BatchProducerModule,
SettlementModule,
SettlementSigner: InMemoryMinaSigner,
BridgingModule,
Mempool: PrivateMempool,
TaskQueue: LocalTaskQueue,
LocalTaskWorker: LocalTaskWorkerModule.from(
VanillaTaskWorkerModules.allTasks()
),
SequencerStartupModule,
}),
});

Expand All @@ -40,16 +64,46 @@ export default async function (options: LoadEnvOptions) {
},
Sequencer: {
...DefaultConfigs.inMemoryDatabase(),
...DefaultConfigs.settlementScript({
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
preset: options.env as Environment,
}),
BaseLayer: {
network: {
// eslint-disable-next-line max-len
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions,@typescript-eslint/no-unsafe-assignment
type: process.env.MINA_NETWORK as any,
graphql: process.env.MINA_NODE_GRAPHQL!,
archive: process.env.MINA_ARCHIVE_GRAPHQL!,
accountManager: process.env.MINA_ACCOUNT_MANAGER!,
},
},
SettlementSigner: {
feepayer: PrivateKey.fromBase58(
process.env.PROTOKIT_SEQUENCER_PRIVATE_KEY!
),
contractKeys: [
PrivateKey.fromBase58(
process.env.PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY!
),
PrivateKey.fromBase58(
process.env.PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY!
),
PrivateKey.fromBase58(
process.env.PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY!
),
],
},
FeeStrategy: {},
BatchProducerModule: {},
SettlementModule: {
addresses: undefined,
},
BridgingModule: {
addresses: undefined,
},
SequencerStartupModule: {},
TaskQueue: {
simulatedDuration: 0,
},
LocalTaskWorker: VanillaTaskWorkerModules.defaultConfig(),
Mempool: {},
},
});

Expand Down
3 changes: 3 additions & 0 deletions packages/deployment/src/queue/BullQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ export class BullQueue

const queue = new Queue<TaskPayload, TaskPayload>(queueName, {
connection: redis,
defaultJobOptions: {
attempts: this.config.retryAttempts ?? 2,
},
});
const events = new QueueEvents(queueName, { connection: redis });

Expand Down
15 changes: 15 additions & 0 deletions packages/protocol/src/Constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { log } from "@proto-kit/common";

const constants = {
STATE_TRANSITION_BATCH_SIZE: 4,
BLOCK_ARGUMENT_BATCH_SIZE: 4,
Expand All @@ -9,6 +11,7 @@ const prefix = "PROTOKIT";
export const Constants = {
getConstant<Key extends keyof typeof constants>(
name: Key,
// TODO Remove this pattern and delegate parsing to the called - this is bad imo
transform: (arg: string) => (typeof constants)[Key]
): (typeof constants)[Key] {
const env = process.env[name] ?? process.env[`${prefix}_${name}`];
Expand All @@ -18,4 +21,16 @@ export const Constants = {
return constants[name];
}
},

printAllConstants() {
const constantsString =
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
(Object.keys(constants) as (keyof typeof constants)[])
.map((name) => {
const constant = Constants.getConstant(name, parseInt);
return `${name}=${constant}`;
})
.join(", ");
log.info("Protocol constants: ", constantsString);
},
};
3 changes: 3 additions & 0 deletions packages/sequencer/src/sequencer/SequencerStartupModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ContractArgsRegistry,
MandatoryProtocolModulesRecord,
Protocol,
ProtocolConstants,
RuntimeVerificationKeyRootService,
} from "@proto-kit/protocol";
import {
Expand Down Expand Up @@ -143,6 +144,8 @@ export class SequencerStartupModule
}

public async start() {
ProtocolConstants.printAllConstants();

const flow = this.flowCreator.createFlow("compile-circuits", {});

this.protocol.dependencyContainer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { SettlementUtils } from "../../utils/SettlementUtils";

@injectable()
export class BridgingDeployInteraction implements DeployInteraction {
private utils: SettlementUtils;

public constructor(
@inject("AddressRegistry")
private readonly addressRegistry: AddressRegistry,
Expand All @@ -33,7 +35,9 @@ export class BridgingDeployInteraction implements DeployInteraction {
private readonly feeStrategy: FeeStrategy,
@inject("TransactionSender")
private readonly transactionSender: MinaTransactionSender
) {}
) {
this.utils = new SettlementUtils(this.baseLayer, this.signer);
}

protected settlementContractModule(): SettlementContractModule<BridgingSettlementModulesRecord> {
return this.protocol.dependencyContainer.resolve(
Expand All @@ -59,7 +63,8 @@ export class BridgingDeployInteraction implements DeployInteraction {

const feepayer = this.signer.getFeepayerKey();

const nonce = options?.nonce ?? 0;
const nonce =
options?.nonce ?? (await this.utils.fetchNonce(feepayer)) ?? 0;

const sm = this.settlementContractModule();
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { SettlementUtils } from "../../utils/SettlementUtils";

@injectable()
export class VanillaDeployInteraction implements DeployInteraction {
private utils: SettlementUtils;

public constructor(
@inject("AddressRegistry")
private readonly addressRegistry: AddressRegistry,
Expand All @@ -33,7 +35,9 @@ export class VanillaDeployInteraction implements DeployInteraction {
private readonly feeStrategy: FeeStrategy,
@inject("TransactionSender")
private readonly transactionSender: MinaTransactionSender
) {}
) {
this.utils = new SettlementUtils(this.baseLayer, this.signer);
}

protected settlementContractModule(): SettlementContractModule<MandatorySettlementModulesRecord> {
return this.protocol.dependencyContainer.resolve(
Expand Down Expand Up @@ -62,7 +66,8 @@ export class VanillaDeployInteraction implements DeployInteraction {

const feepayer = this.signer.getFeepayerKey();

const nonce = options?.nonce ?? 0;
const nonce =
options?.nonce ?? (await this.utils.fetchNonce(feepayer)) ?? 0;

const sm = this.settlementContractModule();
const { SettlementContract: settlementContract } = sm.createContracts({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from "@proto-kit/protocol";
import { match } from "ts-pattern";
import { inject, injectable } from "tsyringe";
import { hashWithPrefix, noop, range } from "@proto-kit/common";
import { hashWithPrefix, log, noop, range } from "@proto-kit/common";

import { distinctByPredicate } from "../../helpers/utils";
import type { MinaBaseLayer } from "../../protocol/baselayer/MinaBaseLayer";
Expand Down Expand Up @@ -173,17 +173,26 @@ export class MinaTransactionSimulator {
const getAccountSafe = () => {
try {
return Mina.getAccount(publicKey, tokenId);
} catch {
} catch (e) {
log.trace(e);
return undefined;
}
};
const account = match(fetchedAccount)
.with(undefined, () => getAccountSafe())
.with({ account: undefined }, () => getAccountSafe())
.with({ account: undefined }, (e) => {
// TODO Check if it's a "account not found" error, and if it's not then display the error
// (as it's probably networking related)
log.trace(e.error);
return getAccountSafe();
})
.with({ error: undefined }, (v) => v.account)
.exhaustive();

if (account !== undefined) {
log.trace(
`Reloaded account ${account.publicKey.toBase58()}, ${account.balance.toJSON()} MINA`
);
addCachedAccount(account);
this.loaded[key] = account;
}
Expand Down
26 changes: 25 additions & 1 deletion packages/sequencer/src/settlement/utils/SettlementUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import {
Bool,
fetchAccount,
Field,
Mina,
PrivateKey,
PublicKey,
Transaction,
UInt32,
} from "o1js";
import { mapSequential } from "@proto-kit/common";
import { log, mapSequential } from "@proto-kit/common";

import type { MinaBaseLayer } from "../../protocol/baselayer/MinaBaseLayer";
import { MinaSigner } from "../MinaSigner";
Expand All @@ -27,6 +28,29 @@ export class SettlementUtils {
private readonly signer: MinaSigner
) {}

public async fetchNonce(publicKey: PublicKey): Promise<number | undefined> {
const account = await this.safeFetchAccount(publicKey);
if (account !== undefined) {
return parseInt(account.nonce.toString(), 10);
}
return undefined;
}

public async safeFetchAccount(publicKey: PublicKey, tokenId?: Field) {
const isLocal = this.baseLayer.isLocalBlockChain();
if (isLocal && Mina.hasAccount(publicKey, tokenId)) {
return Mina.getAccount(publicKey, tokenId);
} else if (!isLocal) {
const fetchResult = await fetchAccount({ publicKey, tokenId });
if (fetchResult.account !== undefined) {
return fetchResult.account;
} else {
log.info(fetchResult.error);
}
}
return undefined;
}

public signTransaction(
tx: Transaction<false, false>,
options: SignTransactionOptions = {}
Expand Down
Loading