Skip to content
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
41 changes: 41 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

permissions: {}

on:
push:
Comment thread
JohnGuilding marked this conversation as resolved.
branches: [main]
pull_request:
workflow_dispatch:

env:
FOUNDRY_PROFILE: ci

jobs:
check:
name: Foundry project
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Show Forge version
run: forge --version

- name: Run Forge fmt
run: forge fmt --check

- name: Run Forge build
run: forge build --sizes

- name: Run Forge tests
run: forge test -vvv
env:
ETH_RPC_URL: ${{ secrets.ETH_RPC_URL }}
142 changes: 5 additions & 137 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,139 +1,7 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Foundry
/cache
/out

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
# Environment
.env
.env.*
!.env.example

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Sveltekit cache directory
.svelte-kit/

# vitepress build output
**/.vitepress/dist

# vitepress cache directory
**/.vitepress/cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# Firebase cache directory
.firebase/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v3
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Vite logs files
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.claude
6 changes: 6 additions & 0 deletions .gitmodules
Comment thread
JohnGuilding marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/contract"]
path = lib/contract
url = https://github.com/Railgun-Privacy/contract
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"[solidity]": {
"editor.defaultFormatter": "JuanBlanco.solidity",
"editor.formatOnSave": true
},
"solidity.formatter": "forge"
}
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# private-transfers-benchmarks
A set of adapters to run structured benchmarks for private transfers protocols

## Test

`forge test -vv`
11 changes: 11 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"lib/contract": {
"rev": "9ec09123eb140fdaaf3a5ff1f29d634c353630cd"
},
"lib/forge-std": {
"tag": {
"name": "v1.14.0",
"rev": "1801b0541f4fda118a10798fd3486bb7051c5dd6"
}
}
}
9 changes: 9 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.28"
remappings = ["@railgun/=lib/contract/contracts/"]

[rpc_endpoints]
mainnet = "${ETH_RPC_URL}"
1 change: 1 addition & 0 deletions lib/contract
Submodule contract added at 9ec091
1 change: 1 addition & 0 deletions lib/forge-std
Submodule forge-std added at 1801b0
3 changes: 3 additions & 0 deletions snapshots/RailgunSendBenchmark.json
Comment thread
JohnGuilding marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"railgun_send": "1024078"
}
135 changes: 135 additions & 0 deletions test/RailgunTransact.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {Test, console} from "forge-std/Test.sol";
import {
Transaction,
SnarkProof,
G1Point,
G2Point,
BoundParams,
CommitmentCiphertext,
CommitmentPreimage,
TokenData,
TokenType,
UnshieldType
} from "@railgun/logic/Globals.sol";

interface IRailgunRelay {
function transact(Transaction[] calldata transactions) external;
}

// Reference tx: 0x9691b06aeb81ae709ad478942a5307c5e5cc4597074f5b60e11b2033c1584580
// Gas cost: cast receipt 0x9691b06aeb81ae709ad478942a5307c5e5cc4597074f5b60e11b2033c1584580 gasUsed --rpc-url $ETH_RPC_URL
contract RailgunSendBenchmark is Test {
IRailgunRelay constant RELAY = IRailgunRelay(0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9);

address constant SENDER = 0x03CbE58799c0EB9AABAB3212886bfcA10A418299;

// Fork at block before the reference tx so nullifiers are unspent.
// TODO: fork at latest once we have proof generation logic.
uint256 constant FORK_BLOCK = 24_421_959;

// The reference tx's gas price
uint256 constant TX_GAS_PRICE = 283_628_746;

function test_send() public {
string memory rpcUrl = vm.envOr("ETH_RPC_URL", string("https://eth.llamarpc.com"));
vm.createSelectFork(rpcUrl, FORK_BLOCK);
vm.txGasPrice(TX_GAS_PRICE);

Transaction[] memory txs = new Transaction[](1);
txs[0] = _buildTransaction();

vm.prank(SENDER);
vm.startSnapshotGas("railgun_send");
RELAY.transact(txs);
uint256 gasUsed = vm.stopSnapshotGas("railgun_send");

console.log("scenario: railgun_send");
console.log("forkBlock:", block.number);
console.log("gasUsed: ", gasUsed);
}

function _buildTransaction() internal pure returns (Transaction memory) {
Comment thread
JohnGuilding marked this conversation as resolved.
SnarkProof memory proof = SnarkProof({
a: G1Point({
x: 0x03d6861e17bf2babb298bb06b69a003f55252b756eab01614acdc89217f5c232,
y: 0x26e0db51c595e77a7041450e8034484976a5ef1509543ba63a3c10f541be3ae0
}),
b: G2Point({
x: [
uint256(0x2b286954d2cc7d4cea7b50450d5c7c072c2a8bd2c76bd8c921ada087d84d26e1),
uint256(0x1091cd885152612e830fb275301648d5f0f0f891a9b0bbd39b3cf390fd907f4c)
],
y: [
uint256(0x11dc536a27865e54c3ec085a532814663448a8ff79b20a7824b949574c8bd9fd),
uint256(0x1ac326f30e8798a39f48bc894f1fc94f644ef3b0089bf41eed564ee6e96cff6b)
]
}),
c: G1Point({
x: 0x2fa47504b90d2920e69465871244194d196550355551b9c5b23117e0e31c56b3,
y: 0x1d024b5ac8dd75a6f5f27c34e7c9c4c568bca186ddd6c64c4eeae051a7acf048
})
});

bytes32[] memory nullifiers = new bytes32[](2);
nullifiers[0] = 0x13c9423325c5d638bf183d242aa9f9b864e4b42b749b00a19950d13d10529ef8;
nullifiers[1] = 0x2a7eb0332c12e3fb1920e62ee6bff72c53c9ac036b340f7003ba978a4b497855;

bytes32[] memory commitments = new bytes32[](2);
commitments[0] = 0x088699b561e26726c43c482201168a153e623d4dc91c70d5ea15959dbe4aa370;
commitments[1] = 0x06e8dcbb2b237226f4cd2da22acde99d63bd75997a68d89ea660a90ad789d679;

CommitmentCiphertext[] memory ciphertexts = new CommitmentCiphertext[](2);
ciphertexts[0] = CommitmentCiphertext({
ciphertext: [
bytes32(0x7d429023249ead0df72b6fbcbc26fa7264033426d5b5934b89ae41e9088def76),
bytes32(0xb4b58e502443c2f79e8891d8c21653dcdc9af33b1af0b2fd662a260450075cbf),
bytes32(0xdc07ad6a7167345f0e798825786d2324f24505cadb6cea1602263dd146febb35),
bytes32(0x83d9085ce23ef4e52372dc68599853274ff383f05d4209cfd62dc10e41192226)
],
blindedSenderViewingKey: 0x67c7c4f4bf7d695c49508d9341db62f258656cbd3680caa0524f6ceccf8dcfdb,
blindedReceiverViewingKey: 0x70db540142462d9f2e494928c8f473cba28c05a46c279b34c546042ad7e98209,
annotationData: hex"33f172f5005e9a92310ecc740c389523b147fc7e09d0f5df198a7496fae843ad2aaa3dba091c93c8716570c64ce04bcc711cc689c10bec659d28ffb487fa",
memo: hex""
});
ciphertexts[1] = CommitmentCiphertext({
ciphertext: [
bytes32(0xbbd1240440d6679e22bb11eec05057373e8e1ef31a6ab0a964a4667517ca108e),
bytes32(0x35aaa5137133d43350b5f99a21dc97a793c638f3fc1207c3670cd73712fd6dd5),
bytes32(0x1c81ab00cd19b2d5db398f3140e2d2f2b95f4cf2d0475fc2bedbf3171aaa0654),
bytes32(0x2ac5a7eb3d337aaa488f172eb86c8a5e8eeca5883e38f7824baa9f9d09e39852)
],
blindedSenderViewingKey: 0xc422f463519d3ec701d9d763b477d580070f2d5d76feb3a55d6634de3064c8ba,
blindedReceiverViewingKey: 0x94e9d2e6d6507c9446062d750396c37d901f3a7d65517a74f66adecc11514539,
annotationData: hex"a5d946a5411a0f3c697ae08bf3f44f64b27f52be7491faaa7797d0ae9c88e193c5f5f5d180ceb044f9cc62bc9d8c46dc50d803f98237d304c9d3604f47a1",
memo: hex""
});

BoundParams memory boundParams = BoundParams({
treeNumber: 2,
minGasPrice: 283_628_746,
unshield: UnshieldType.NONE,
chainID: 1,
adaptContract: address(0),
adaptParams: bytes32(0),
commitmentCiphertext: ciphertexts
});

CommitmentPreimage memory unshieldPreimage = CommitmentPreimage({
npk: bytes32(0),
token: TokenData({tokenType: TokenType.ERC20, tokenAddress: address(0), tokenSubID: 0}),
value: 0
});

return Transaction({
proof: proof,
merkleRoot: 0x03309f5fdc4b5c0d38e7c1fbe75be39758dfe5fa63982bf1663ee9ccf3471dc5,
nullifiers: nullifiers,
commitments: commitments,
boundParams: boundParams,
unshieldPreimage: unshieldPreimage
});
}
}