Skip to content

Commit

Permalink
revert transaction builder
Browse files Browse the repository at this point in the history
  • Loading branch information
rus7hex committed Jun 12, 2024
1 parent 5fcdbcc commit 73c7bce
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 57 deletions.
16 changes: 4 additions & 12 deletions packages/app-eth/src/app-eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ class SecuxETH {

return wrapResult({
commandData: data,
rawTx: builder.serialize()
rawTx: toCommunicationData(builder.serialize())
});
}

Expand Down Expand Up @@ -363,11 +363,7 @@ class SecuxETH {
const data = SecuxETH.prepareSignSerialized(path, args, option);
const rsp = await this.Exchange(getBuffer(data));
let signature = Buffer.from(SecuxETH.resolveSignature(rsp), "hex");
signature = getBuffer(
ETHTransactionBuilder
.deserialize(args)
.getSignature(signature)
);
signature = ETHTransactionBuilder.deserialize(getBuffer(args)).getSignature(signature);

return {
raw_tx: SecuxETH.resolveTransaction(rsp, args),
Expand Down Expand Up @@ -414,11 +410,7 @@ class SecuxETH {
const { commandData, rawTx } = func(path, args, option);
const rsp = await this.Exchange(getBuffer(commandData));
let signature = Buffer.from(SecuxETH.resolveSignature(rsp), "hex");
signature = getBuffer(
ETHTransactionBuilder
.deserialize(getBuffer(rawTx))
.getSignature(signature)
);
signature = ETHTransactionBuilder.deserialize(getBuffer(rawTx)).getSignature(signature);

return {
raw_tx: SecuxETH.resolveTransaction(rsp, rawTx),
Expand Down Expand Up @@ -474,7 +466,7 @@ export function prepareSign(path: string, builder: ETHTransactionBuilder, tp?: T

return wrapResult({
commandData: buf,
rawTx: builder.serialize()
rawTx: toCommunicationData(builder.serialize())
});
}

Expand Down
77 changes: 32 additions & 45 deletions packages/app-eth/src/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { BigNumber } from 'bignumber.js';
import ow from "ow";
import { ow_tx1559 } from './interface';
import { Logger } from "@secux/utility";
import { communicationData, getBuffer, toCommunicationData, wrapResult } from "@secux/utility/lib/communication";
export { getBuilder, ETHTransactionBuilder, EIP1559Builder };
const logger = Logger?.child({ id: "ethereum" });

Expand All @@ -41,11 +40,9 @@ function getBuilder(data: any) {
return new ETHTransactionBuilder(data);
}

const _ethTx = new WeakMap();
const __tx = new WeakMap();
class ETHTransactionBuilder {
static deserialize(serialized: communicationData): ETHTransactionBuilder {
serialized = getBuffer(serialized);

static deserialize(serialized: Buffer): ETHTransactionBuilder {
// legacy transaction
if (serialized[0] >= 0xc0) {
const values = rlp.decode(serialized);
Expand Down Expand Up @@ -97,7 +94,7 @@ class ETHTransactionBuilder {

constructor(tx: any) {
const _tx = { ...tx };
_ethTx.set(this, _tx);
__tx.set(this, _tx);

if (typeof tx.chainId === "string") {
let str = tx.chainId.slice(2);
Expand Down Expand Up @@ -143,9 +140,9 @@ class ETHTransactionBuilder {
/**
*
* @param {boolean} toHash
* @returns {communicationData} transaction (keccak256 hashed or not)
* @returns {Buffer} transaction (keccak256 hashed or not)
*/
serialize(toHash: boolean = false): communicationData {
serialize(toHash: boolean = false): Buffer {
const transaction = [
...this.prepare(),
handleRLPValue(this.tx.chainId ?? 0x00),
Expand All @@ -155,44 +152,39 @@ class ETHTransactionBuilder {

const encoded = rlp.encode(transaction);

const result = (toHash) ? Buffer.from(keccak256.update(encoded).digest()) : encoded;
return toCommunicationData(result);
return (toHash) ? Buffer.from(keccak256.update(encoded).digest()) : encoded;
}

/**
* sign transaction
* @param {communicationData} sigData
* @returns {communicationData} signed transaction
* @param {string} signature
* @returns {Buffer} signed transaction
*/
withSignature(sigData: communicationData): communicationData {
if (!this.verify(sigData)) throw Error("invalid signature");
withSignature(sig: Buffer): Buffer {
if (!this.verify(sig)) throw Error("invalid signature");

sigData = getBuffer(this.getSignature(sigData));
sig = this.getSignature(sig);
const transaction = [
...this.prepare(),
handleRLPValue(sigData.slice(64)),
trimZeroForRLP(sigData.slice(0, 32)),
trimZeroForRLP(sigData.slice(32, 64))
handleRLPValue(sig.slice(64)),
trimZeroForRLP(sig.slice(0, 32)),
trimZeroForRLP(sig.slice(32, 64))
];

const serialized = rlp.encode(transaction);
return toCommunicationData(serialized);
return rlp.encode(transaction);
}

getSignature(sigData: communicationData): communicationData {
sigData = getBuffer(sigData);
getSignature(sig: Buffer): Buffer {
const chainId = parseInt(Buffer.from(this.tx.chainId ?? [0]).toString("hex"), 16);
const offset = (chainId > 0) ? chainId * 2 + 35 : 27;
let v_hex = (sigData[64] + offset).toString(16);
let v_hex = (sig[64] + offset).toString(16);
if (v_hex.length % 2 !== 0) v_hex = `0${v_hex}`;
const v = Buffer.from(v_hex, "hex");

const signature = Buffer.concat([
sigData.slice(0, 64),
return Buffer.concat([
sig.slice(0, 64),
v
]);

return toCommunicationData(signature);
}

protected prepare() {
Expand All @@ -206,8 +198,7 @@ class ETHTransactionBuilder {
];
}

protected verify(data: communicationData): boolean {
data = getBuffer(data);
protected verify(data: Buffer): boolean {
const sig = data.slice(0, 64);
try {
secp256k1.ecdsaRecover(sig, data.readUint8(64), this.serialize(true));
Expand All @@ -224,14 +215,13 @@ class ETHTransactionBuilder {
return parseInt(Buffer.from(this.tx.chainId).toString("hex"), 16);
}

get tx() { return _ethTx.get(this); }
get txJSON() { return wrapResult(this.tx); }
get tx() { return __tx.get(this); }
}

class EIP1559Builder extends ETHTransactionBuilder {
constructor(tx: any) {
super(tx);
const _tx = _ethTx.get(this);
const _tx = __tx.get(this);

// deal with compatibale fields
const priorityFee = tx.maxPriorityFeePerGas || tx.priorityFee;
Expand All @@ -250,39 +240,36 @@ class EIP1559Builder extends ETHTransactionBuilder {
}
}

serialize(toHash: boolean = false): communicationData {
serialize(toHash: boolean = false): Buffer {
const transaction = this.prepare();

const encoded = Buffer.concat([
EIP1559_TransactionType,
rlp.encode(transaction)
]);

const result = (toHash) ? Buffer.from(keccak256.update(encoded).digest()) : encoded;
return toCommunicationData(result);
return (toHash) ? Buffer.from(keccak256.update(encoded).digest()) : encoded;
}

withSignature(sigData: communicationData): communicationData {
if (!this.verify(sigData)) throw Error("invalid signature");
withSignature(sig: Buffer): Buffer {
if (!this.verify(sig)) throw Error("invalid signature");

sigData = getBuffer(sigData);
const transaction = [
...this.prepare(),
handleRLPValue(sigData[64]),
trimZeroForRLP(sigData.slice(0, 32)),
trimZeroForRLP(sigData.slice(32, 64))
handleRLPValue(sig[64]),
trimZeroForRLP(sig.slice(0, 32)),
trimZeroForRLP(sig.slice(32, 64))
];
const encoded = rlp.encode(transaction);

const serialized = Buffer.concat([
return Buffer.concat([
EIP1559_TransactionType,
encoded
]);
return toCommunicationData(serialized);
}

getSignature(sigData: communicationData): communicationData {
return sigData;
getSignature(sig: Buffer): Buffer {
return sig;
}

protected prepare() {
Expand Down

0 comments on commit 73c7bce

Please sign in to comment.