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

Enhanced Input Validation and Code Refactoring for Starknet Address Script #1553

Merged
merged 6 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
7 changes: 5 additions & 2 deletions cairo/kakarot-ssj/scripts/compute_create_address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ prompt([
name: "from",
message: "Enter from address:",
default: "0xF39FD6E51AAD88F6F4CE6AB8827279CFFFB92266",
filter: (value) => value as Address,
},
{
type: "input",
Expand All @@ -31,21 +32,23 @@ prompt([
default:
"0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806306661abd1461004e578063371303c01461006c5780636d4ce63c14610076578063b3bcfa8214610094575b5f80fd5b61005661009e565b60405161006391906100f7565b60405180910390f35b6100746100a3565b005b61007e6100bd565b60405161008b91906100f7565b60405180910390f35b61009c6100c5565b005b5f5481565b60015f808282546100b4919061013d565b92505081905550565b5f8054905090565b60015f808282546100d69190610170565b92505081905550565b5f819050919050565b6100f1816100df565b82525050565b5f60208201905061010a5f8301846100e8565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610147826100df565b9150610152836100df565b925082820190508082111561016a57610169610110565b5b92915050565b5f61017a826100df565b9150610185836100df565b925082820390508181111561019d5761019c610110565b5b9291505056fea26469706673582212207e792fcff28a4bf0bad8675c5bc2288b07835aebaa90b8dc5e0df19183fb72cf64736f6c63430008160033",
when: (answers) => answers.opcode === "CREATE2",
filter: (value) => value as Hex,
},
{
type: "input",
name: "salt",
message: "Enter salt or press Enter for default [0xbeef]:",
default: "0xbeef",
when: (answers) => answers.opcode === "CREATE2",
filter: (value) => value.startsWith("0x") ? (value as Hex) : ("0x" + value as Hex),
},
]).then((answers) => {
let address: Address;
if (answers.opcode === "CREATE") {
address = getContractAddress({
opcode: "CREATE",
from: answers.from as Address,
nonce: answers.nonce,
nonce: answers.nonce as BigInt,
});
} else if (answers.opcode === "CREATE2") {
address = getContractAddress({
Expand All @@ -56,5 +59,5 @@ prompt([
});
}

console.log(`Generated Address: ${address!}`);
console.log(`Generated Address: ${address}`);
});
144 changes: 58 additions & 86 deletions cairo/kakarot-ssj/scripts/compute_rlp_encoding.ts
Original file line number Diff line number Diff line change
@@ -1,160 +1,132 @@
// This js script helps in creating unsigned and signed RLP data for tests

import { ethers, toBeArray } from "ethers";
import dotevn from "dotenv";
import { ethers } from "ethers";
import dotenv from "dotenv";
import readline from "readline";
import { readFileSync } from "fs";
import { readFileSync, existsSync } from "fs";

dotevn.config();
dotenv.config();

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

const question = (query: string): Promise<string> => {
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
rl.question(query, (answer) => {
resolve(answer);
});
});
};

const main = async () => {
const { Transaction, Wallet } = ethers;
const { decodeRlp, getBytes } = ethers;
const { Transaction, Wallet, keccak256, RLP } = ethers;

if (!process.env.PRIVATE_KEY_RLP_SCRIPT) {
console.log(
"missing private key in environment, please provide PRIVATE_KEY_RLP_SCRIPT environment variable",
console.error(
"Missing private key in environment. Please provide PRIVATE_KEY_RLP_SCRIPT in .env"
);
process.exit(1);
}

const wallet = new Wallet(process.env.PRIVATE_KEY_RLP_SCRIPT);
console.log("address of the wallet is", wallet.address);
console.log("Address of the wallet:", wallet.address);

let tx_type = parseInt(
await question(
"enter transaction, 0: legacy, 1: 2930, 2:1559, 3: inc_counter, 4: y_parity_false eip1559: ",
),
"Enter transaction type (0: legacy, 1: 2930, 2: 1559, 3: inc_counter, 4: y_parity_false eip1559): "
)
);

// for type 0 and type 1
let tx;

let txFilePath: string;
switch (tx_type) {
case 0:
tx = JSON.parse(
readFileSync("./scripts/data/input_legacy_tx.json", "utf-8"),
);
txFilePath = "./scripts/data/input_legacy_tx.json";
break;
case 1:
tx = JSON.parse(
readFileSync("./scripts/data/input_access_list_tx.json", "utf-8"),
);
txFilePath = "./scripts/data/input_access_list_tx.json";
break;
case 2:
tx = JSON.parse(
readFileSync("./scripts/data/input_fee_tx.json", "utf-8"),
);
txFilePath = "./scripts/data/input_fee_tx.json";
break;
case 3:
tx_type = 1;
tx = JSON.parse(
readFileSync(
"./scripts/data/input_eip_2930_counter_inc_tx.json",
"utf-8",
),
);
txFilePath = "./scripts/data/input_eip_2930_counter_inc_tx.json";
break;
case 4:
tx_type = 2;
tx = JSON.parse(
readFileSync(
"./scripts/data/input_eip1559_y_parity_false.json",
"utf-8",
),
);
txFilePath = "./scripts/data/input_eip1559_y_parity_false.json";
break;
default:
throw new Error(
`transaction type ${tx_type} isn't a valid transaction type`,
);
throw new Error(`Invalid transaction type: ${tx_type}`);
}

if (!existsSync(txFilePath)) {
throw new Error(`Transaction file not found: ${txFilePath}`);
}

const tx = JSON.parse(readFileSync(txFilePath, "utf-8"));
const transaction = Transaction.from(tx);
transaction.type = tx_type;

let signed_tx = await wallet.signTransaction(transaction);

console.log("unsigned serialized tx ----->", transaction.unsignedSerialized);
console.log("unsigned transaction hash", transaction.hash);

// const bytes = getBytes(signedTX);
const bytes = getBytes(transaction.unsignedSerialized);

console.log("unsigned RLP encoded bytes for the transaction: ");
const signed_tx = await wallet.signTransaction(transaction);
console.log("Unsigned serialized tx:", transaction.unsignedSerialized);
console.log("Unsigned transaction hash:", transaction.hash);

// this prints unsigned RLP encoded bytes of the transaction
bytes.forEach((v) => {
console.log(v, ",");
});
console.log("\n");

let bytes2 = Uint8Array.from(transaction.type == 0 ? bytes : bytes.slice(1));

let decodedRlp = decodeRlp(bytes2);
console.log("decoded RLP is for unsigned transaction ....\n", decodedRlp);

let bytes3 = getBytes(signed_tx);
const unsignedBytes = ethers.getBytes(transaction.unsignedSerialized);
console.log("Unsigned RLP encoded bytes:");
console.log(unsignedBytes.map((v) => `${v},`).join(" "));

console.log("signed RLP encoded bytes for the transaction: ");
const unsignedBytes2 = Uint8Array.from(
transaction.type === 0 ? unsignedBytes : unsignedBytes.slice(1)
);
let decodedRlp = RLP.decode(unsignedBytes2);
console.log("Decoded RLP for unsigned transaction:\n", decodedRlp);

// this prints unsigned RLP encoded bytes of the transaction
bytes3.forEach((v) => {
console.log(v, ",");
});
console.log("\n");
const signedBytes = ethers.getBytes(signed_tx);
console.log("Signed RLP encoded bytes:");
console.log(signedBytes.map((v) => `${v},`).join(" "));

bytes3 = Uint8Array.from(transaction.type == 0 ? bytes3 : bytes3.slice(1));
decodedRlp = decodeRlp(bytes3);
console.log("signed decoded RLP for signed transaction ....\n", decodedRlp);
const signedBytes2 = Uint8Array.from(
transaction.type === 0 ? signedBytes : signedBytes.slice(1)
);
decodedRlp = RLP.decode(signedBytes2);
console.log("Signed decoded RLP for signed transaction:\n", decodedRlp);

const hash = ethers.keccak256(bytes);
console.log("the hash over which the signature was made:", hash);
const hash = keccak256(unsignedBytes);
console.log("Hash over which the signature was made:", hash);

console.log("signature details: ");
console.log("Signature details:");
const v = decodedRlp[decodedRlp.length - 3];
const r = decodedRlp[decodedRlp.length - 2];
const s = decodedRlp[decodedRlp.length - 1];

const y_parity =
tx_type == 0
tx_type === 0
? get_y_parity(BigInt(v), BigInt(tx.chainId))
: parseInt(v, 16) == 1;
console.log("r: ", r);
console.log("s: ", s);
if (tx_type == 0) {
console.log("v: ", v);
: parseInt(v, 16) === 1;
console.log("r:", r);
console.log("s:", s);
if (tx_type === 0) {
console.log("v:", v);
}
console.log("y parity: ", y_parity);
console.log("y parity:", y_parity);

rl.close();
process.exit(0);
};

const get_y_parity = (v: bigint, chain_id: bigint): boolean => {
let y_parity = v - (chain_id * BigInt(2) + BigInt(35));
if (y_parity == BigInt(0) || y_parity == BigInt(1)) {
return y_parity == BigInt(1);
if (y_parity === BigInt(0) || y_parity === BigInt(1)) {
return y_parity === BigInt(1);
}

y_parity = v - (chain_id * BigInt(2) + BigInt(36));
if (y_parity == BigInt(0) || y_parity == BigInt(1)) {
return y_parity == BigInt(1);
if (y_parity === BigInt(0) || y_parity === BigInt(1)) {
return y_parity === BigInt(1);
}

throw new Error("invalid v value");
throw new Error("Invalid v value");
};

main();
24 changes: 18 additions & 6 deletions cairo/kakarot-ssj/scripts/compute_starknet_address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,36 @@ inquirer
name: "classHashInput",
message: "Enter the class hash:",
validate: (input) => {
if (input.trim() === "") {
return "Class hash is required.";
if (!/^0x[0-9a-fA-F]+$/.test(input.trim())) {
return "Please enter a valid hexadecimal class hash.";
}
return true;
},
},
{
type: "input",
name: "saltInput",
message: "Enter the salt",
message: "Enter the salt:",
default: "0x65766d5f61646472657373",
validate: (input) => {
if (!/^0x[0-9a-fA-F]+$/.test(input.trim())) {
return "Please enter a valid hexadecimal salt.";
}
return true;
},
},
{
type: "input",
name: "deployerInput",
message: "Enter the deployer address",
message: "Enter the deployer address:",
default:
"0x7753aaa1814b9f978fd93b66453ae87419b66d764fbf9313847edeb0283ef63",
validate: (input) => {
if (!/^0x[0-9a-fA-F]+$/.test(input.trim())) {
return "Please enter a valid hexadecimal deployer address.";
}
return true;
},
},
])
.then((answers) => {
Expand All @@ -35,7 +47,7 @@ inquirer

const CONSTRUCTOR_CALLDATA = [deployerAddress, salt];

function compute_starknet_address() {
function computeStarknetAddress() {
return hash.calculateContractAddressFromHash(
salt,
classHash,
Expand All @@ -44,5 +56,5 @@ inquirer
);
}

console.log("Pre-computed Starknet Address: " + compute_starknet_address());
console.log("Pre-computed Starknet Address:", computeStarknetAddress());
});
Loading