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

Rename CTC to Inputs #54

Merged
merged 4 commits into from
Oct 11, 2023
Merged
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
8 changes: 4 additions & 4 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

## Data availability

Data availability is provided by L1 via posting the data as `calldata` to the `CTC` contract.
You can find the contract responsible for this in the [CanonicalTransactionChain.sol](./packages/contracts/src/CanonicalTransactionChain.sol).
Data availability is provided by L1 via posting the data as `calldata` to the `Inputs` contract.
You can find the contract responsible for this in the [Inputs.sol](./packages/contracts/src/Inputs.sol).
It has a single function that can be called by anyone, and it's going to emit an event for easier retrieval of new batches.
Users can either send transactions to the contract or the sequencer that is later going to call the same function.

Expand All @@ -17,7 +17,7 @@ These addresses are considered to be faucets, if their supply runs out, there ar
### Data fetching

Data is fetched by the [BatchDownloader.ts](./packages/node/src/core/BatchDownloader.ts), after it's downloaded, the `calldata` is extracted and passed through the State Transition Function by [StateUpdater.ts](./packages/node/src/core/StateUpdater.ts), the results are stored in the database.
BatchDownloader relies on the events emitted by the `CTC` to find all the necessary `calldata`.
BatchDownloader relies on the events emitted by the `Inputs` to find all the necessary `calldata`.

### State transition function

Expand Down Expand Up @@ -52,4 +52,4 @@ Each sequencer has it's own mempool and transactions by default are sorted by th

# Wallet / Frontend

The frontend is stored in [here](./packages/wallet/).
The frontend is stored in [here](./packages/wallet/).
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Build Your Own Rollup - A simple rollup implementation for educational purposes.

If you want to read the code and understand how it works you should start with the following files:

1. [The smart contract](./packages/contracts/src/CanonicalTransactionChain.sol)
1. [The smart contract](./packages/contracts/src/Inputs.sol)
2. [The node](./packages/node/src/index.ts)

For more details about the architecture, see [here](./ARCHITECTURE.md).
Expand Down
10 changes: 4 additions & 6 deletions packages/contracts/scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,11 @@ async function main(): Promise<void> {
await startPerpetualHardhatNode()
}

const ctcFactory = await ethers.getContractFactory(
'CanonicalTransactionChain',
)
const ctc = await ctcFactory.deploy()
await ctc.deployed()
const inputsFactory = await ethers.getContractFactory('Inputs')
const inputs = await inputsFactory.deploy()
await inputs.deployed()

console.log(`CanonicalTransactionChain deployed to ${ctc.address}`)
console.log(`Inputs deployed to ${inputs.address}`)
}

main().catch((error) => {
Expand Down
10 changes: 5 additions & 5 deletions packages/contracts/src/Caller.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './CanonicalTransactionChain.sol';
import './Inputs.sol';

// Only used for testing
contract Caller {
CanonicalTransactionChain ctc;
Inputs inputs;

constructor(address ctcContract) {
ctc = CanonicalTransactionChain(ctcContract);
constructor(address inputsContract) {
inputs = Inputs(inputsContract);
}

function appendBatch(bytes calldata batch) public {
ctc.appendBatch(batch);
inputs.appendBatch(batch);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract CanonicalTransactionChain {
contract Inputs {
event BatchAppended(address sender);

function appendBatch(bytes calldata) external {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
import { assert, expect } from 'chai'
import hre from 'hardhat'

describe('CanonicalTransactionChain', () => {
describe('Inputs', () => {
const randomBytes = '0x12345678907654321234567890987654321234567890987654'

async function getDeployer(): Promise<SignerWithAddress> {
Expand All @@ -14,23 +14,19 @@ describe('CanonicalTransactionChain', () => {
it('Should emit BatchAppended event', async () => {
const deployer = await getDeployer()

const ctcFactory = await hre.ethers.getContractFactory(
'CanonicalTransactionChain',
)
const ctc = await ctcFactory.deploy()
const inputsFactory = await hre.ethers.getContractFactory('Inputs')
const inputs = await inputsFactory.deploy()

await expect(ctc.appendBatch(randomBytes))
.to.emit(ctc, 'BatchAppended')
await expect(inputs.appendBatch(randomBytes))
.to.emit(inputs, 'BatchAppended')
.withArgs(await deployer.getAddress())
})

it('Should revert if called from another contract', async () => {
const ctcFactory = await hre.ethers.getContractFactory(
'CanonicalTransactionChain',
)
const ctc = await ctcFactory.deploy()
const inputsFactory = await hre.ethers.getContractFactory('Inputs')
const inputs = await inputsFactory.deploy()
const callerFactory = await hre.ethers.getContractFactory('Caller')
const caller = await callerFactory.deploy(ctc.address)
const caller = await callerFactory.deploy(inputs.address)

await expect(caller.appendBatch(randomBytes)).to.be.reverted
})
Expand Down
42 changes: 21 additions & 21 deletions packages/node/src/core/BatchPoster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ describe(BatchPoster.name, () => {
}),
})
const client = mockObject<EthereumPrivateClient>({
writeToCTCContract: mockFn().returns(null),
writeToInputsContract: mockFn().returns(null),
})
const mempool = mockObject<Mempool>({
popNHighestFee: mockFn()
Expand All @@ -109,12 +109,12 @@ describe(BatchPoster.name, () => {

expect(mempool.empty).toHaveBeenCalledTimes(0)
expect(mempool.popNHighestFee).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenNthCalledWith(
expect(client.writeToInputsContract).toHaveBeenCalledTimes(2)
expect(client.writeToInputsContract).toHaveBeenNthCalledWith(
1,
modelTx1SerializedHex,
)
expect(client.writeToCTCContract).toHaveBeenNthCalledWith(
expect(client.writeToInputsContract).toHaveBeenNthCalledWith(
2,
modelTx2SerializedHex,
)
Expand Down Expand Up @@ -145,7 +145,7 @@ describe(BatchPoster.name, () => {
}),
})
const client = mockObject<EthereumPrivateClient>({
writeToCTCContract: mockFn().returns(null),
writeToInputsContract: mockFn().returns(null),
})
const mempool = mockObject<Mempool>({
popNHighestFee: mockFn()
Expand All @@ -166,8 +166,8 @@ describe(BatchPoster.name, () => {

expect(mempool.empty).toHaveBeenCalledTimes(0)
expect(mempool.popNHighestFee).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenCalledTimes(1)
expect(client.writeToCTCContract).toHaveBeenNthCalledWith(
expect(client.writeToInputsContract).toHaveBeenCalledTimes(1)
expect(client.writeToInputsContract).toHaveBeenNthCalledWith(
1,
modelTx1SerializedHex,
)
Expand Down Expand Up @@ -198,7 +198,7 @@ describe(BatchPoster.name, () => {
}),
})
const client = mockObject<EthereumPrivateClient>({
writeToCTCContract: mockFn().returns(null),
writeToInputsContract: mockFn().returns(null),
})
const mempool = mockObject<Mempool>({
popNHighestFee: mockFn()
Expand All @@ -219,7 +219,7 @@ describe(BatchPoster.name, () => {

expect(mempool.empty).toHaveBeenCalledTimes(0)
expect(mempool.popNHighestFee).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenCalledTimes(0)
expect(client.writeToInputsContract).toHaveBeenCalledTimes(0)
})

it('does not submit empty transactions', async () => {
Expand Down Expand Up @@ -247,7 +247,7 @@ describe(BatchPoster.name, () => {
}),
})
const client = mockObject<EthereumPrivateClient>({
writeToCTCContract: mockFn().returns(null),
writeToInputsContract: mockFn().returns(null),
})
const mempool = mockObject<Mempool>({
popNHighestFee: mockFn()
Expand All @@ -269,12 +269,12 @@ describe(BatchPoster.name, () => {

expect(mempool.empty).toHaveBeenCalledTimes(0)
expect(mempool.popNHighestFee).toHaveBeenCalledTimes(3)
expect(client.writeToCTCContract).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenNthCalledWith(
expect(client.writeToInputsContract).toHaveBeenCalledTimes(2)
expect(client.writeToInputsContract).toHaveBeenNthCalledWith(
1,
modelTx1SerializedHex,
)
expect(client.writeToCTCContract).toHaveBeenNthCalledWith(
expect(client.writeToInputsContract).toHaveBeenNthCalledWith(
2,
modelTx2SerializedHex,
)
Expand Down Expand Up @@ -305,7 +305,7 @@ describe(BatchPoster.name, () => {
}),
})
const client = mockObject<EthereumPrivateClient>({
writeToCTCContract: mockFn().returns(null),
writeToInputsContract: mockFn().returns(null),
})
const mempool = mockObject<Mempool>({
popNHighestFee: mockFn()
Expand All @@ -326,7 +326,7 @@ describe(BatchPoster.name, () => {

expect(mempool.empty).toHaveBeenCalledTimes(0)
expect(mempool.popNHighestFee).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenCalledTimes(0)
expect(client.writeToInputsContract).toHaveBeenCalledTimes(0)
})

it('does not submit transaction if balance if nonce is wrong', async () => {
Expand Down Expand Up @@ -354,7 +354,7 @@ describe(BatchPoster.name, () => {
}),
})
const client = mockObject<EthereumPrivateClient>({
writeToCTCContract: mockFn().returns(null),
writeToInputsContract: mockFn().returns(null),
})
const mempool = mockObject<Mempool>({
popNHighestFee: mockFn()
Expand All @@ -375,7 +375,7 @@ describe(BatchPoster.name, () => {

expect(mempool.empty).toHaveBeenCalledTimes(0)
expect(mempool.popNHighestFee).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenCalledTimes(0)
expect(client.writeToInputsContract).toHaveBeenCalledTimes(0)
})

it('submits transactions every flush period seconds', async () => {
Expand Down Expand Up @@ -403,7 +403,7 @@ describe(BatchPoster.name, () => {
}),
})
const client = mockObject<EthereumPrivateClient>({
writeToCTCContract: mockFn()
writeToInputsContract: mockFn()
.throwsOnce(new Error('failed'))
.returns(null),
})
Expand All @@ -426,12 +426,12 @@ describe(BatchPoster.name, () => {

expect(mempool.empty).toHaveBeenCalledTimes(0)
expect(mempool.popNHighestFee).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenCalledTimes(2)
expect(client.writeToCTCContract).toHaveBeenNthCalledWith(
expect(client.writeToInputsContract).toHaveBeenCalledTimes(2)
expect(client.writeToInputsContract).toHaveBeenNthCalledWith(
1,
modelTx1SerializedHex,
)
expect(client.writeToCTCContract).toHaveBeenNthCalledWith(
expect(client.writeToInputsContract).toHaveBeenNthCalledWith(
2,
modelTx2SerializedHex,
)
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/core/BatchPoster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class BatchPoster {
}

const batchBytes = serializeBatch(validTransactions)
await this.client.writeToCTCContract(batchBytes)
await this.client.writeToInputsContract(batchBytes)
this.logger.info('Submitted', {
count: candidateTransactions.length,
leftInMempool: this.mempool.size(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { abi } from '../../core/abi'
import { EthereumPrivateClient } from './EthereumPrivateClient'

describe(EthereumPrivateClient.name, () => {
describe(EthereumPrivateClient.prototype.writeToCTCContract.name, () => {
it('writes data to the CTC contract using private provider', async () => {
describe(EthereumPrivateClient.prototype.writeToInputsContract.name, () => {
it('writes data to the Inputs contract using private provider', async () => {
const publicProvider = mockObject<PublicClient>({})
const privateProvider = mockObject<WalletClient>({
writeContract: mockFn().returnsOnce(''),
Expand All @@ -25,7 +25,7 @@ describe(EthereumPrivateClient.name, () => {
Logger.SILENT,
)

await ethereumClient.writeToCTCContract(Hex('0x1234'))
await ethereumClient.writeToInputsContract(Hex('0x1234'))

expect(privateProvider.writeContract).toHaveBeenCalledWith({
address: ctcContractAddress.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class EthereumPrivateClient extends EthereumClient {
this.logger = this.logger.for(this)
}

async writeToCTCContract(batchBytes: Hex): Promise<void> {
async writeToInputsContract(batchBytes: Hex): Promise<void> {
await this.privateProvider.writeContract({
address: this.ctcContractAddress.toString(),
abi: abi,
Expand Down