From a598367515c53aeb43ebc2078d85c6cc4ee86111 Mon Sep 17 00:00:00 2001 From: TucksonDev Date: Tue, 25 Nov 2025 16:47:50 +0000 Subject: [PATCH] Add prepareNodeConfig script --- ...nfigurationFromChainCreationTransaction.ts | 136 ++++ src/abis.ts | 591 ++++++++++++++++++ 2 files changed, 727 insertions(+) create mode 100644 scripts/prepareNodeConfigurationFromChainCreationTransaction.ts create mode 100644 src/abis.ts diff --git a/scripts/prepareNodeConfigurationFromChainCreationTransaction.ts b/scripts/prepareNodeConfigurationFromChainCreationTransaction.ts new file mode 100644 index 0000000..6e6d1e0 --- /dev/null +++ b/scripts/prepareNodeConfigurationFromChainCreationTransaction.ts @@ -0,0 +1,136 @@ +import { createPublicClient, decodeFunctionData, http } from 'viem'; +import { + createRollupPrepareTransactionReceipt, + createRollupPrepareTransaction, + ChainConfig, +} from '@arbitrum/orbit-sdk'; +import { + prepareDasConfig, + saveDasNodeConfigFile, + buildNodeConfiguration, +} from '../src/utils/node-configuration'; +import { + getChainConfigFromChainId, + withFallbackPrivateKey, + getRpcUrl, + saveCoreContractsFile, +} from '../src/utils/helpers'; +import { chainIsAnytrust } from '../src/utils/chain-info-helpers'; +import { createRollupWithDataCostEstimationAbi } from '../src/abis'; +import 'dotenv/config'; + +// Check for required env variables +if ( + !process.env.PARENT_CHAIN_ID || + !process.env.CHAIN_OWNER_PRIVATE_KEY || + !process.env.BATCH_POSTER_PRIVATE_KEY || + !process.env.STAKER_PRIVATE_KEY || + !process.env.CHAIN_CREATION_TRANSACTION_HASH +) { + throw new Error( + 'The following environment variables must be present: PARENT_CHAIN_ID, CHAIN_OWNER_PRIVATE_KEY, BATC_POSTER_PRIVATE_KEY, STAKER_PRIVATE_KEY, CHAIN_CREATION_TRANSACTION_HASH', + ); +} + +// Load or generate a random batch poster account +const batchPosterPrivateKey = withFallbackPrivateKey(process.env.BATCH_POSTER_PRIVATE_KEY); + +// Load or generate a random staker account +const validatorPrivateKey = withFallbackPrivateKey(process.env.STAKER_PRIVATE_KEY); + +// Set the parent chain and create a public client for it +const parentChainInformation = getChainConfigFromChainId(Number(process.env.PARENT_CHAIN_ID)); +const parentChainRpc = process.env.PARENT_CHAIN_RPC_URL || getRpcUrl(parentChainInformation); +const parentChainPublicClient = createPublicClient({ + chain: parentChainInformation, + transport: http(parentChainRpc), +}); + +const main = async () => { + console.log('**************************************************************'); + console.log('* Prepare node configuration from chain creation transaction *'); + console.log('**************************************************************'); + console.log(''); + + // tx hash for the transaction to create rollup + const transactionHash = process.env.CHAIN_CREATION_TRANSACTION_HASH as `0x${string}`; + + // get the transaction + const transaction = createRollupPrepareTransaction( + await parentChainPublicClient.getTransaction({ hash: transactionHash }), + ); + + const transactionReceipt = createRollupPrepareTransactionReceipt( + await parentChainPublicClient.getTransactionReceipt({ + hash: transactionHash, + }), + ); + + // Get the chain configuration + // const config = transaction.getInputs()[0].config; + // NOTE: if using a different ABI than the canonical one, decode manually + // using the following snippet + const { args } = decodeFunctionData({ + abi: createRollupWithDataCostEstimationAbi, + data: transaction.input, + }) as { + functionName: 'createRollup'; + args: [ + { + config: { + chainConfig: string; + stakeToken: `0x${string}`; + }; + }, + ]; + }; + if (!args) { + throw new Error(`Could not decode function data for transaction ${transactionHash}`); + } + const config = args[0].config; + + // Extract the chainConfig and the stakeToken + const chainConfig: ChainConfig = JSON.parse(config.chainConfig); + const stakeToken: `0x${string}` = config.stakeToken; + + // Get the core contracts from the transaction receipt + const coreContracts = transactionReceipt.getCoreContracts(); + + // Save core contracts in JSON file + const coreContractsFilePath = saveCoreContractsFile(coreContracts); + console.log(`Core contracts written to ${coreContractsFilePath}`); + + // Build node configuration + const { batchPosterfilePath, stakerFilePath, rpcFilePath } = buildNodeConfiguration( + chainConfig, + coreContracts, + batchPosterPrivateKey, + validatorPrivateKey, + stakeToken, + parentChainInformation, + parentChainRpc, + ); + console.log(`Batch poster config written to ${batchPosterfilePath}`); + console.log(`Staker config written to ${stakerFilePath}`); + console.log(`RPC config written to ${rpcFilePath}`); + + // If we want to use AnyTrust, we need to: + // 1. set the right keyset in the SequencerInbox + // 2. generate the DAS node configuration + if (chainIsAnytrust()) { + // + // Prepare DAS node config + // + const dasNodeConfig = prepareDasConfig(parentChainRpc, coreContracts.sequencerInbox); + const dasConfigFilePath = saveDasNodeConfigFile(dasNodeConfig); + console.log(`DAS node config written to ${dasConfigFilePath}`); + } +}; + +// Calling main +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/src/abis.ts b/src/abis.ts new file mode 100644 index 0000000..f447f61 --- /dev/null +++ b/src/abis.ts @@ -0,0 +1,591 @@ +export const createRollupWithDataCostEstimationAbi = [ + { + inputs: [ + { + internalType: 'address', + name: 'initialOwner', + type: 'address', + }, + { + internalType: 'contract BridgeCreator', + name: '_bridgeCreator', + type: 'address', + }, + { + internalType: 'contract IOneStepProofEntry', + name: '_osp', + type: 'address', + }, + { + internalType: 'contract IEdgeChallengeManager', + name: '_challengeManagerLogic', + type: 'address', + }, + { + internalType: 'contract IRollupAdmin', + name: '_rollupAdminLogic', + type: 'address', + }, + { + internalType: 'contract IRollupUser', + name: '_rollupUserLogic', + type: 'address', + }, + { + internalType: 'contract IUpgradeExecutor', + name: '_upgradeExecutorLogic', + type: 'address', + }, + { + internalType: 'address', + name: '_validatorWalletCreator', + type: 'address', + }, + { + internalType: 'contract DeployHelper', + name: '_l2FactoriesDeployer', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'previousOwner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'newOwner', + type: 'address', + }, + ], + name: 'OwnershipTransferred', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'rollupAddress', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'nativeToken', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'inboxAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'outbox', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'rollupEventInbox', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'challengeManager', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'adminProxy', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'sequencerInbox', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'bridge', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'upgradeExecutor', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'validatorWalletCreator', + type: 'address', + }, + ], + name: 'RollupCreated', + type: 'event', + }, + { + anonymous: false, + inputs: [], + name: 'TemplatesUpdated', + type: 'event', + }, + { + inputs: [], + name: 'bridgeCreator', + outputs: [ + { + internalType: 'contract BridgeCreator', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'challengeManagerTemplate', + outputs: [ + { + internalType: 'contract IEdgeChallengeManager', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + components: [ + { + internalType: 'uint64', + name: 'confirmPeriodBlocks', + type: 'uint64', + }, + { + internalType: 'address', + name: 'stakeToken', + type: 'address', + }, + { + internalType: 'uint256', + name: 'baseStake', + type: 'uint256', + }, + { + internalType: 'bytes32', + name: 'wasmModuleRoot', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + internalType: 'address', + name: 'loserStakeEscrow', + type: 'address', + }, + { + internalType: 'uint256', + name: 'chainId', + type: 'uint256', + }, + { + internalType: 'string', + name: 'chainConfig', + type: 'string', + }, + { + internalType: 'uint256', + name: 'minimumAssertionPeriod', + type: 'uint256', + }, + { + internalType: 'uint64', + name: 'validatorAfkBlocks', + type: 'uint64', + }, + { + internalType: 'uint256[]', + name: 'miniStakeValues', + type: 'uint256[]', + }, + { + components: [ + { + internalType: 'uint256', + name: 'delayBlocks', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'futureBlocks', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'delaySeconds', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'futureSeconds', + type: 'uint256', + }, + ], + internalType: 'struct ISequencerInbox.MaxTimeVariation', + name: 'sequencerInboxMaxTimeVariation', + type: 'tuple', + }, + { + internalType: 'uint256', + name: 'layerZeroBlockEdgeHeight', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'layerZeroBigStepEdgeHeight', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'layerZeroSmallStepEdgeHeight', + type: 'uint256', + }, + { + components: [ + { + components: [ + { + internalType: 'bytes32[2]', + name: 'bytes32Vals', + type: 'bytes32[2]', + }, + { + internalType: 'uint64[2]', + name: 'u64Vals', + type: 'uint64[2]', + }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { + internalType: 'enum MachineStatus', + name: 'machineStatus', + type: 'uint8', + }, + { + internalType: 'bytes32', + name: 'endHistoryRoot', + type: 'bytes32', + }, + ], + internalType: 'struct AssertionState', + name: 'genesisAssertionState', + type: 'tuple', + }, + { + internalType: 'uint256', + name: 'genesisInboxCount', + type: 'uint256', + }, + { + internalType: 'address', + name: 'anyTrustFastConfirmer', + type: 'address', + }, + { + internalType: 'uint8', + name: 'numBigStepLevel', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'challengeGracePeriodBlocks', + type: 'uint64', + }, + { + components: [ + { + internalType: 'uint64', + name: 'threshold', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'max', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'replenishRateInBasis', + type: 'uint64', + }, + ], + internalType: 'struct BufferConfig', + name: 'bufferConfig', + type: 'tuple', + }, + { + internalType: 'uint256', + name: 'dataCostEstimate', + type: 'uint256', + }, + ], + internalType: 'struct Config', + name: 'config', + type: 'tuple', + }, + { + internalType: 'address[]', + name: 'validators', + type: 'address[]', + }, + { + internalType: 'uint256', + name: 'maxDataSize', + type: 'uint256', + }, + { + internalType: 'address', + name: 'nativeToken', + type: 'address', + }, + { + internalType: 'bool', + name: 'deployFactoriesToL2', + type: 'bool', + }, + { + internalType: 'uint256', + name: 'maxFeePerGasForRetryables', + type: 'uint256', + }, + { + internalType: 'address[]', + name: 'batchPosters', + type: 'address[]', + }, + { + internalType: 'address', + name: 'batchPosterManager', + type: 'address', + }, + { + internalType: 'contract IFeeTokenPricer', + name: 'feeTokenPricer', + type: 'address', + }, + { + internalType: 'address', + name: 'customOsp', + type: 'address', + }, + ], + internalType: 'struct RollupCreator.RollupDeploymentParams', + name: 'deployParams', + type: 'tuple', + }, + ], + name: 'createRollup', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'l2FactoriesDeployer', + outputs: [ + { + internalType: 'contract DeployHelper', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'osp', + outputs: [ + { + internalType: 'contract IOneStepProofEntry', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'owner', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'rollupAdminLogic', + outputs: [ + { + internalType: 'contract IRollupAdmin', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'rollupUserLogic', + outputs: [ + { + internalType: 'contract IRollupUser', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract BridgeCreator', + name: '_bridgeCreator', + type: 'address', + }, + { + internalType: 'contract IOneStepProofEntry', + name: '_osp', + type: 'address', + }, + { + internalType: 'contract IEdgeChallengeManager', + name: '_challengeManagerLogic', + type: 'address', + }, + { + internalType: 'contract IRollupAdmin', + name: '_rollupAdminLogic', + type: 'address', + }, + { + internalType: 'contract IRollupUser', + name: '_rollupUserLogic', + type: 'address', + }, + { + internalType: 'contract IUpgradeExecutor', + name: '_upgradeExecutorLogic', + type: 'address', + }, + { + internalType: 'address', + name: '_validatorWalletCreator', + type: 'address', + }, + { + internalType: 'contract DeployHelper', + name: '_l2FactoriesDeployer', + type: 'address', + }, + ], + name: 'setTemplates', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'newOwner', + type: 'address', + }, + ], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'upgradeExecutorLogic', + outputs: [ + { + internalType: 'contract IUpgradeExecutor', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'validatorWalletCreator', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + stateMutability: 'payable', + type: 'receive', + }, +];