2
0
mirror of synced 2025-02-23 19:48:28 +00:00

Safer transaction serialization, matching signature.v with chainId (#708).

This commit is contained in:
Richard Moore 2020-02-04 00:48:45 -05:00
parent 15bb840907
commit edb7c5da91
No known key found for this signature in database
GPG Key ID: 665176BE8E9DC651

View File

@ -2,7 +2,7 @@
import { getAddress } from "@ethersproject/address";
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
import { arrayify, BytesLike, DataOptions, hexDataSlice, hexlify, hexZeroPad, SignatureLike, splitSignature, stripZeros, } from "@ethersproject/bytes";
import { arrayify, BytesLike, DataOptions, hexDataSlice, hexlify, hexZeroPad, isBytesLike, SignatureLike, splitSignature, stripZeros, } from "@ethersproject/bytes";
import { Zero } from "@ethersproject/constants";
import { keccak256 } from "@ethersproject/keccak256";
import { checkProperties } from "@ethersproject/properties";
@ -109,17 +109,30 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur
raw.push(hexlify(value));
});
if (transaction.chainId != null && transaction.chainId !== 0) {
raw.push(hexlify(transaction.chainId));
let chainId = 0;
if (transaction.chainId != null) {
// A chainId was provided; if non-zero we'll use EIP-155
chainId = transaction.chainId;
if (typeof(chainId) !== "number") {
logger.throwArgumentError("invalid transaction.chainId", "transaction", transaction);
}
} else if (signature && !isBytesLike(signature) && signature.v > 28) {
// No chainId provided, but the signature is signing with EIP-155; derive chainId
chainId = Math.floor((signature.v - 35) / 2);
}
// We have an EIP-155 transaction (chainId was specified and non-zero)
if (chainId !== 0) {
raw.push(hexlify(chainId));
raw.push("0x");
raw.push("0x");
}
const unsignedTransaction = RLP.encode(raw);
// Requesting an unsigned transation
if (!signature) {
return unsignedTransaction;
return RLP.encode(raw);
}
// The splitSignature will ensure the transaction has a recoveryParam in the
@ -128,11 +141,18 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur
// We pushed a chainId and null r, s on for hashing only; remove those
let v = 27 + sig.recoveryParam
if (raw.length === 9) {
if (chainId !== 0) {
raw.pop();
raw.pop();
raw.pop();
v += transaction.chainId * 2 + 8;
v += chainId * 2 + 8;
// If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it!
if (sig.v > 28 && sig.v !== v) {
logger.throwArgumentError("transaction.chainId/signature.v mismatch", "signature", signature);
}
} else if (sig.v !== v) {
logger.throwArgumentError("transaction.chainId/signature.v mismatch", "signature", signature);
}
raw.push(hexlify(v));