Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timeboost mode for nitro-testnode #95

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
47 changes: 46 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,26 @@ services:
ports:
- "127.0.0.1:8547:8547"
- "127.0.0.1:8548:8548"
- "127.0.0.1:9549:8549"
- "127.0.0.1:9642:9642"
volumes:
- "seqdata:/home/user/.arbitrum/local/nitro"
- "l1keystore:/home/user/l1keystore"
- "config:/config"
- "tokenbridge-data:/tokenbridge-data"
command: --conf.file /config/sequencer_config.json --node.feed.output.enable --node.feed.output.port 9642 --http.api net,web3,eth,txpool,debug --node.seq-coordinator.my-url ws://sequencer:8548 --graphql.enable --graphql.vhosts * --graphql.corsdomain *
command:
- --conf.file=/config/sequencer_config.json
- --node.feed.output.enable
- --node.feed.output.port=9642
- --http.api=net,web3,eth,txpool,debug,timeboost
- --node.seq-coordinator.my-url=ws://sequencer:8548
- --graphql.enable
- --graphql.vhosts=*
- --graphql.corsdomain=*
- --auth.addr=0.0.0.0
- --auth.api=auctioneer,eth,validation
- --auth.jwtsecret=/config/jwt.hex
- --auth.origins=*
depends_on:
- geth

Expand Down Expand Up @@ -415,6 +428,37 @@ services:
command:
- --conf.file=/config/l2_das_mirror.json

timeboost-auctioneer:
pid: host # allow debugging
image: nitro-node-dev-testnode
entrypoint: /usr/local/bin/autonomous-auctioneer
volumes:
- "config:/config"
- "timeboost-auctioneer-data:/data"
- "l1keystore:/home/user/l1keystore"
command:
- --conf.file=/config/autonomous_auctioneer_config.json
depends_on:
- redis

timeboost-bid-validator:
pid: host # allow debugging
image: nitro-node-dev-testnode
entrypoint: /usr/local/bin/autonomous-auctioneer
ports:
- "127.0.0.1:9372:8547"
volumes:
- "config:/config"
command:
- --conf.file=/config/bid_validator_config.json
- --http.addr=0.0.0.0
- --http.vhosts=*
- --http.corsdomain=*
- --http.api=auctioneer
- --log-level=INFO
depends_on:
- redis

volumes:
l1data:
consensus:
Expand All @@ -434,3 +478,4 @@ volumes:
das-committee-a-data:
das-committee-b-data:
das-mirror-data:
timeboost-auctioneer-data:
20 changes: 19 additions & 1 deletion scripts/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
FROM node:18-bullseye-slim
# Stage 1: Base build environment
FROM node:18-bullseye-slim AS base
WORKDIR /workspace
COPY ./package.json ./yarn.lock ./
RUN yarn

# Stage 2: Copy files and run build
FROM base AS pre-build
COPY ./*.ts ./tsconfig.json ./
COPY ./nitro-contracts ./nitro-contracts

RUN if [ -f "./nitro-contracts/DEV_CONTRACTS" ]; then \
echo "Overwriting @arbitrum/nitro-contracts with local version"; \
rm -rf node_modules/@arbitrum/nitro-contracts; \
cp -a ./nitro-contracts node_modules/@arbitrum/nitro-contracts; \
else \
echo "local nitro-contracts directory not found, using npm version"; \
fi
# At this stage, the intermediate image will stop
RUN echo "Intermediate image created before yarn build"

# Stage 3: Final build
FROM pre-build AS final
RUN yarn build
ENTRYPOINT ["node", "index.js"]
8 changes: 6 additions & 2 deletions scripts/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as crypto from "crypto";
import { runStress } from "./stress";
const path = require("path");

const specialAccounts = 6;
const specialAccounts = 7;

async function writeAccounts() {
for (let i = 0; i < specialAccounts; i++) {
Expand Down Expand Up @@ -47,6 +47,9 @@ export function namedAccount(
if (name == "l2owner") {
return specialAccount(5);
}
if (name == "auctioneer") {
return specialAccount(6);
}
if (name.startsWith("user_")) {
return new ethers.Wallet(
ethers.utils.sha256(ethers.utils.toUtf8Bytes(name))
Expand Down Expand Up @@ -85,7 +88,8 @@ export function namedAddress(

export const namedAccountHelpString =
"Valid account names:\n" +
" funnel | sequencer | validator | l2owner - known keys used by l2\n" +
" funnel | sequencer | validator | l2owner\n" +
" | auctioneer - known keys used by l2\n" +
" l3owner | l3sequencer - known keys used by l3\n" +
" user_[Alphanumeric] - key will be generated from username\n" +
" threaduser_[Alphanumeric] - same as user_[Alphanumeric]_thread_[thread-id]\n" +
Expand Down
78 changes: 75 additions & 3 deletions scripts/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ function writeConfigs(argv: any) {
},
"execution": {
"sequencer": {
"enable": false,
"enable": false
},
"forwarding-target": "null",
},
Expand Down Expand Up @@ -309,6 +309,13 @@ function writeConfigs(argv: any) {
sequencerConfig.node["seq-coordinator"].enable = true
sequencerConfig.execution["sequencer"].enable = true
sequencerConfig.node["delayed-sequencer"].enable = true
if (argv.timeboost) {
// Initially we create it disabled but then replace it using test-node.bash
// once we have the contract and auctioneer address.
sequencerConfig.execution.sequencer.timeboost = {
"enable": false
};
}
fs.writeFileSync(path.join(consts.configpath, "sequencer_config.json"), JSON.stringify(sequencerConfig))

let posterConfig = JSON.parse(baseConfJSON)
Expand Down Expand Up @@ -385,7 +392,7 @@ function writeL2ChainConfig(argv: any) {
"EnableArbOS": true,
"AllowDebugPrecompiles": true,
"DataAvailabilityCommittee": argv.anytrust,
"InitialArbOSVersion": 32,
"InitialArbOSVersion": 32, // TODO For Timeboost, this still needs to be set to 31
"InitialChainOwner": argv.l2owner,
"GenesisBlockNum": 0
}
Expand Down Expand Up @@ -514,6 +521,59 @@ function dasBackendsJsonConfig(argv: any) {
return backends
}

export const writeTimeboostConfigsCommand = {
command: "write-timeboost-configs",
describe: "writes configs for the timeboost autonomous auctioneer and bid validator",
builder: {
"auction-contract": {
string: true,
describe: "auction contract address",
demandOption: true
},
},
handler: (argv: any) => {
writeAutonomousAuctioneerConfig(argv)
writeBidValidatorConfig(argv)
}
}

function writeAutonomousAuctioneerConfig(argv: any) {
const autonomousAuctioneerConfig = {
"auctioneer-server": {
"auction-contract-address": argv.auctionContract,
"db-directory": "/data",
"redis-url": "redis://redis:6379",
"sequencer-endpoint": "ws://sequencer:8549",
"sequencer-jwt-path": "/config/jwt.hex",
"wallet": {
"account": namedAddress("auctioneer"),
"password": consts.l1passphrase,
"pathname": consts.l1keystore
},
},
"bid-validator": {
"enable": false
}
}
const autonomousAuctioneerConfigJSON = JSON.stringify(autonomousAuctioneerConfig)
fs.writeFileSync(path.join(consts.configpath, "autonomous_auctioneer_config.json"), autonomousAuctioneerConfigJSON)
}

function writeBidValidatorConfig(argv: any) {
const bidValidatorConfig = {
"auctioneer-server": {
"enable": false
},
"bid-validator": {
"auction-contract-address": argv.auctionContract,
"redis-url": "redis://redis:6379",
"sequencer-endpoint": "http://sequencer:8547"
}
}
const bidValidatorConfigJSON = JSON.stringify(bidValidatorConfig)
fs.writeFileSync(path.join(consts.configpath, "bid_validator_config.json"), bidValidatorConfigJSON)
}

export const writeConfigCommand = {
command: "write-config",
describe: "writes config files",
Expand All @@ -538,7 +598,11 @@ export const writeConfigCommand = {
describe: "DAS committee member B BLS pub key",
default: ""
},

timeboost: {
boolean: true,
describe: "run sequencer in timeboost mode",
default: false
},
},
handler: (argv: any) => {
writeConfigs(argv)
Expand Down Expand Up @@ -620,3 +684,11 @@ export const writeL2DASKeysetConfigCommand = {
writeL2DASKeysetConfig(argv)
}
}

function auctioneerServerConfig(argv: any) {
const conf = {
"auctioneer-server": {
}
}
return conf
}
83 changes: 74 additions & 9 deletions scripts/ethcommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,17 @@ import * as L1AtomicTokenBridgeCreator from "@arbitrum/token-bridge-contracts/bu
import * as ERC20 from "@openzeppelin/contracts/build/contracts/ERC20.json";
import * as fs from "fs";
import { ARB_OWNER } from "./consts";
import * as TransparentUpgradeableProxy from "@openzeppelin/contracts/build/contracts/TransparentUpgradeableProxy.json"
const path = require("path");

let ExpressLaneAuctionContract: any;
try {
ExpressLaneAuctionContract = require("@arbitrum/nitro-contracts/out/ExpressLaneAuction.sol/ExpressLaneAuction.json");
} catch (e) {
console.warn("ExpressLaneAuction contract JSON not found. This is expected if not running with --l2timeboost.");
}


async function sendTransaction(argv: any, threadId: number) {
const account = namedAccount(argv.from, threadId).connect(argv.provider)
const startNonce = await account.getTransactionCount("pending")
Expand Down Expand Up @@ -293,7 +302,8 @@ export const createERC20Command = {
builder: {
deployer: {
string: true,
describe: "account (see general help)"
describe: "account (see general help)",
demandOption: true
},
bridgeable: {
boolean: true,
Expand All @@ -319,10 +329,7 @@ export const createERC20Command = {
const l1provider = new ethers.providers.WebSocketProvider(argv.l1url);
const l2provider = new ethers.providers.WebSocketProvider(argv.l2url);

const deployerWallet = new Wallet(
ethers.utils.sha256(ethers.utils.toUtf8Bytes(argv.deployer)),
l1provider
);
const deployerWallet = namedAccount(argv.deployer).connect(l1provider)

const tokenAddress = await deployERC20Contract(deployerWallet, argv.decimals);
const token = new ethers.Contract(tokenAddress, ERC20.abi, deployerWallet);
Expand Down Expand Up @@ -361,17 +368,75 @@ export const createERC20Command = {

// no l1-l2 token bridge, deploy token on l2 directly
argv.provider = new ethers.providers.WebSocketProvider(argv.l2url);
const deployerWallet = new Wallet(
ethers.utils.sha256(ethers.utils.toUtf8Bytes(argv.deployer)),
argv.provider
);
const deployerWallet = namedAccount(argv.deployer).connect(argv.provider)
const tokenAddress = await deployERC20Contract(deployerWallet, argv.decimals);
console.log("Contract deployed at address:", tokenAddress);

argv.provider.destroy();
},
};

export const deployExpressLaneAuctionContractCommand = {
command: "deploy-express-lane-auction",
describe: "Deploy the ExpressLaneAuction contract",
builder: {
"bidding-token": {
string: true,
describe: "bidding token address",
demandOption: true
},
"auctioneer": {
string: true,
describe: "account name to set as auctioneer and admin on contract (default auctioneer)",
default: "auctioneer"
}
},
handler: async (argv: any) => {
if (!ExpressLaneAuctionContract) {
console.error("ExpressLaneAuctionContract is not available. Ensure that you are using the correct contracts branch.");
process.exit(1);
}

console.log("deploy ExpressLaneAuction contract");
argv.provider = new ethers.providers.WebSocketProvider(argv.l2url);
const l2OwnerWallet = namedAccount("l2owner").connect(argv.provider)
const contractFactory = new ContractFactory(ExpressLaneAuctionContract.abi, ExpressLaneAuctionContract.bytecode, l2OwnerWallet)

const contract = await contractFactory.deploy();
await contract.deployTransaction.wait();
console.log("ExpressLaneAuction contract deployed at address:", contract.address);

const auctioneerAddr = namedAddress(argv.auctioneer)
const initIface = new ethers.utils.Interface(["function initialize((address,address,address,(int64,uint64,uint64,uint64),uint256,address,address,address,address,address,address,address))"])
const initData = initIface.encodeFunctionData("initialize", [[
auctioneerAddr, //_auctioneer
argv.biddingToken, //_biddingToken
auctioneerAddr, //_beneficiary
[
Math.round(Date.now() / 60000) * 60, // offsetTimestamp - most recent minute
60, // roundDurationSeconds
15, // auctionClosingSeconds
15 // reserveSubmissionSeconds
],// RoundTiminginfo
1, // _minReservePrice
auctioneerAddr, //_auctioneerAdmin
auctioneerAddr, //_minReservePriceSetter,
auctioneerAddr, //_reservePriceSetter,
auctioneerAddr, //_reservePriceSetterAdmin,
auctioneerAddr, //_beneficiarySetter,
auctioneerAddr, //_roundTimingSetter,
auctioneerAddr //_masterAdmin
]]);

const proxyFactory = new ethers.ContractFactory(TransparentUpgradeableProxy.abi, TransparentUpgradeableProxy.bytecode, l2OwnerWallet)
const proxy = await proxyFactory.deploy(contract.address, namedAddress("l2owner"), initData)
await proxy.deployed()
console.log("Proxy(ExpressLaneAuction) contract deployed at address:", proxy.address);

argv.provider.destroy();
}
};

// Will revert if the keyset is already valid.
async function setValidKeyset(argv: any, upgradeExecutorAddr: string, sequencerInboxAddr: string, keyset: string){
const innerIface = new ethers.utils.Interface(["function setValidKeyset(bytes)"])
Expand Down
Loading
Loading