Skip to content

Instantly share code, notes, and snippets.

@lucaspere
Created May 3, 2025 15:08
Show Gist options
  • Save lucaspere/7377e5b0c0fb50ee331f04ed3771947c to your computer and use it in GitHub Desktop.
Save lucaspere/7377e5b0c0fb50ee331f04ed3771947c to your computer and use it in GitHub Desktop.
Demonstration of manually signing a legacy Ethereum transaction in TypeScript using RLP, Keccak256 and secp256k1, comparing against the viem library.
import { secp256k1 } from "@noble/curves/secp256k1";
import keccak256 from "keccak256";
import { assert } from "node:console";
import RLP, { Input } from "rlp";
import * as viem from "viem";
import { privateKeyToAccount } from "viem/accounts";
const messageToSign = {
nonce: 0,
gasPrice: viem.parseGwei("20"),
value: viem.parseEther("1"),
gas: 21000n,
to: "0x3535353535353535353535353535353535353535",
data: "0x",
};
const privateKey =
"0xd76e578c0264d4bf7cb6f3e23a8c39feea8d16e39059b4fe69b7ac8e86ed8f5e";
const account = privateKeyToAccount(privateKey);
const signedPrivate = await account.signTransaction({type: "legacy", ...messageToSign} as any);
console.log(`Signed Transaction:`, signedPrivate);
const [rlpBytes,] = inputToRlp([
messageToSign.nonce,
messageToSign.gasPrice,
messageToSign.gas,
messageToSign.to,
messageToSign.value,
messageToSign.data,
]);
const hash = keccak256(Buffer.from(rlpBytes));
const { r, s, recovery} = secp256k1.sign(hash, viem.hexToBytes(privateKey));
const v = 27 + recovery;
const finalListToSign = {
...messageToSign,
r,
s,
v,
};
const [, finalRlpSigned] = inputToRlp([
finalListToSign.nonce,
finalListToSign.gasPrice,
finalListToSign.gas,
finalListToSign.to,
finalListToSign.value,
finalListToSign.data,
finalListToSign.v,
finalListToSign.r,
finalListToSign.s,
]);
function inputToRlp(value: Input) {
const rlp = RLP.encode(value);
const rlpHex = viem.toHex(rlp);
return [rlp, rlpHex];
}
assert(signedPrivate === finalRlpSigned, "Signed transaction does not match");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment