Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6dae739
feat(apis/vara-eth, idea/vara-eth): return back button for uploading …
StackOverflowExcept1on Mar 28, 2026
d66a173
fix kzg-wasm on frontend site
StackOverflowExcept1on Mar 30, 2026
2c152a8
do not upload code on test setup
osipov-mit Mar 30, 2026
dbeb743
fix codec
StackOverflowExcept1on Mar 30, 2026
fe2718d
Merge remote-tracking branch 'origin/main' into av/fix-upload-code
StackOverflowExcept1on Mar 30, 2026
eebc703
fix lint
StackOverflowExcept1on Mar 30, 2026
72acfac
Revert "chore(deps): bump ethexe-common from `933a9b7` to `24b338b` i…
StackOverflowExcept1on Mar 30, 2026
8af6d54
fix serde features
StackOverflowExcept1on Mar 31, 2026
19a820b
switch to gear master
StackOverflowExcept1on Mar 31, 2026
227dfac
fix some nits
StackOverflowExcept1on Mar 31, 2026
83ed58b
update viem dependency
osipov-mit Mar 31, 2026
590c5bd
fix all places with viem fork
StackOverflowExcept1on Mar 31, 2026
2bd77af
Merge remote-tracking branch 'origin/main' into av/fix-upload-code
StackOverflowExcept1on Mar 31, 2026
6e83d01
fix fee
StackOverflowExcept1on Apr 1, 2026
188d803
update viem dependency
osipov-mit Apr 1, 2026
9b1330e
fix undefined
StackOverflowExcept1on Apr 1, 2026
f5ed4b3
console log fee
StackOverflowExcept1on Apr 1, 2026
d670258
fix pkg and feeHistory
StackOverflowExcept1on Apr 1, 2026
9476bda
revert frontend part (will be moved to another PR)
StackOverflowExcept1on Apr 1, 2026
813d827
remove console log
StackOverflowExcept1on Apr 1, 2026
53ae489
bump version, update readme, changelog
osipov-mit Apr 2, 2026
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
4 changes: 3 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ jobs:

- name: "Install: Foundry"
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly-c07d504b4ae67754584f4e05ff0c547a43c50f7b

- name: 'Install dependencies'
run: yarn workspaces focus gear-js @gear-js/api
Expand Down Expand Up @@ -153,7 +155,7 @@ jobs:
if: steps.changed-vara-eth.outputs.any_changed == 'true'
uses: foundry-rs/foundry-toolchain@v1
with:
version: v1.5.0-rc1
version: nightly-c07d504b4ae67754584f4e05ff0c547a43c50f7b

- name: 'Install dependencies'
if: steps.changed-vara-eth.outputs.any_changed == 'true'
Expand Down
35 changes: 23 additions & 12 deletions apis/vara-eth/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apis/vara-eth/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace.package]
version = "0.0.1"
version = "0.1.0"
authors = ["Gear Technologies"]
edition = "2024"
license = "GPL-3.0"
Expand Down
4 changes: 2 additions & 2 deletions apis/vara-eth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@
},
"peerDependencies": {
"kzg-wasm": "1.0.0",
"viem": "^2.39.0"
"viem": "*"
Comment thread
StackOverflowExcept1on marked this conversation as resolved.
},
"devDependencies": {
"@types/ws": "8.18.1",
"kzg-wasm": "1.0.0",
"viem": "2.47.4",
"viem": "https://pkg.pr.new/StackOverflowExcept1on/viem/viem@98e8516",
Comment thread
StackOverflowExcept1on marked this conversation as resolved.
Outdated
"ws": "8.18.3"
},
"files": [
Expand Down
6 changes: 3 additions & 3 deletions apis/vara-eth/programs/injected/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use ethexe_common::{
ToDigest,
ecdsa::{PrivateKey, Signature, SignedMessage},
gprimitives::{ActorId, H256},
injected::{InjectedTransaction, Promise},
ToDigest,
};
use gear_core::rpc::ReplyInfo;
use gear_core_errors::{ReplyCode, SuccessReplyReason};
Expand All @@ -15,10 +15,10 @@ pub fn main() {

let tx = InjectedTransaction {
destination: ActorId::zero(),
payload: Vec::from([0, 1, 2]).into(),
payload: Vec::from([0, 1, 2]).try_into().unwrap(),
value: 256,
reference_block: H256::zero(),
salt: Vec::from([3, 4, 5]).into(),
salt: Vec::from([3, 4, 5]).try_into().unwrap(),
};

println!("hash: <{:?}>", tx.to_digest());
Expand Down
84 changes: 54 additions & 30 deletions apis/vara-eth/src/eth/router.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Address, Hex, TransactionRequest } from 'viem';
import { toHex, zeroAddress, numberToBytes, hexToBytes, bytesToHex, encodeFunctionData } from 'viem';
import { toHex, zeroAddress, hexToBytes, bytesToHex, encodeFunctionData } from 'viem';
import { randomBytes } from '@noble/hashes/utils';
import { loadKZG } from 'kzg-wasm';

Expand Down Expand Up @@ -225,8 +225,7 @@ export class RouterClient extends BaseContractClient implements IRouterContract
* @returns A transaction manager with validation-specific helper functions, including
* the code ID and a function to wait for the code to be validated
*/
private async requestCodeValidation(code: Uint8Array): Promise<TxManagerWithHelpers<CodeValidationHelpers>> {
throw new Error('Not implemented');
public async requestCodeValidation(code: Uint8Array): Promise<TxManagerWithHelpers<CodeValidationHelpers>> {
const codeId = generateCodeHash(code);

const data = encodeFunctionData({
Expand All @@ -235,21 +234,17 @@ export class RouterClient extends BaseContractClient implements IRouterContract
args: [codeId],
});

const blob = prepareBlob(code);

if (blob.length != 4096 * 32) {
throw new Error('Invalid blob size');
}

const blobs = simpleSidecarEncode(code);
const kzg = await loadKZG();

const tx = {
type: 'eip4844' as const,
blobVersion: '7594' as const,
Comment thread
StackOverflowExcept1on marked this conversation as resolved.
data,
to: this.address,
gas: 5_000_000n,
maxFeePerBlobGas: 400_000_000_000n,
blobs: [blob],
blobs,
kzg: {
blobToKzgCommitment: (blob: Uint8Array) => {
const result = kzg.blobToKZGCommitment(bytesToHex(blob)) as Hex;
Expand All @@ -259,6 +254,10 @@ export class RouterClient extends BaseContractClient implements IRouterContract
const result = kzg.computeBlobKZGProof(bytesToHex(blob), bytesToHex(commitment)) as Hex;
return hexToBytes(result);
},
computeCellsAndKzgProofs: (blob: Uint8Array): [Uint8Array[], Uint8Array[]] => {
const [cells, proofs] = kzg.computeCellsAndProofs(bytesToHex(blob)) as [`0x${string}`[], `0x${string}`[]];
return [cells.map((cell) => hexToBytes(cell)), proofs.map((proof) => hexToBytes(proof))];
},
},
chain: null,
};
Expand All @@ -278,6 +277,7 @@ export class RouterClient extends BaseContractClient implements IRouterContract
eventName: 'CodeGotValidated',
onLogs: (logs) => {
for (const log of logs) {
console.log(log);
if (log.args.codeId == codeId) {
if (log.args.valid) {
resolve(true);
Expand Down Expand Up @@ -381,25 +381,49 @@ export function getRouterClient(params: ContractClientParams): RouterClient {
return new RouterClient(params);
}

function prepareBlob(data: Uint8Array) {
// https://docs.rs/alloy/latest/alloy/consensus/struct.SimpleCoder.html#behavior
const BLOB_SIZE = 131_072;
const paddedData = new Uint8Array(BLOB_SIZE);

const dataLength = numberToBytes(data.length, { size: 32 });
const length = new Uint8Array(32);
length.set(dataLength, 0);

paddedData.set(length, 0);

let offset = 32;

while (data.length > 0) {
const chunk = data.slice(0, 31);
paddedData.set(chunk, offset + 1);
offset += 32;
data = data.slice(31);
const BYTES_PER_BLOB = 131_072;
const FIELD_ELEMENTS_PER_BLOB = 4096;
const FE_BYTES = 32;
const USABLE_BYTES_PER_FE = 31;

export function simpleSidecarEncode(data: Uint8Array): Uint8Array[] {
const blobs: Uint8Array[] = [];
let feCount = 0;

const pushEmptyBlob = () => {
blobs.push(new Uint8Array(BYTES_PER_BLOB));
};

const currentBlob = () => {
const index = Math.floor(feCount / FIELD_ELEMENTS_PER_BLOB);
while (blobs.length <= index) pushEmptyBlob();
return blobs[index];
};

const feOffsetInCurrentBlob = () => (feCount % FIELD_ELEMENTS_PER_BLOB) * FE_BYTES;

const ingestFE = (fe: Uint8Array) => {
const blob = currentBlob();
const offset = feOffsetInCurrentBlob();
blob.set(fe, offset);
feCount++;
};

if (data.length === 0) return blobs;

const lenFE = new Uint8Array(FE_BYTES);
const lenBytes = new DataView(lenFE.buffer);
lenBytes.setBigUint64(1, BigInt(data.length));
ingestFE(lenFE);

let offset = 0;
while (offset < data.length) {
const fe = new Uint8Array(FE_BYTES);
const chunkSize = Math.min(USABLE_BYTES_PER_FE, data.length - offset);
fe.set(data.subarray(offset, offset + chunkSize), 1);
offset += chunkSize;
ingestFE(fe);
}

return paddedData;
}
return blobs;
}
Loading
Loading