Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 3 additions & 6 deletions integration_tests/Rpc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
SignedTransaction,
Transaction,
TransferAsset,
U256,
U64
} from "../lib/core/classes";
import {
Expand Down Expand Up @@ -281,7 +280,8 @@ describe("rpc", () => {

test("VerificationFailed", done => {
const signed = tx.sign({ secret: signerSecret, fee: 10, seq });
signed.r = new U256(0);
(signed as any)._signature =
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
sdk.rpc.chain
.sendSignedTransaction(signed)
.then(() => done.fail())
Expand Down Expand Up @@ -683,15 +683,12 @@ describe("rpc", () => {
});

test("Ok", async () => {
const { r, s, v } = signEcdsa(message, secret);
const signature = await sdk.rpc.account.sign(
message,
address,
"my-password"
);
expect(signature).toContain(r);
expect(signature).toContain(s);
expect(signature).toContain(v);
expect(signature).toContain(signEcdsa(message, secret));
});

test("WrongPassword", async done => {
Expand Down
39 changes: 12 additions & 27 deletions src/__test__/secp256k1.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
signEcdsa,
verifyEcdsa,
getPublicFromPrivate,
recoverEcdsa,
getPublicFromPrivate
signEcdsa,
verifyEcdsa
} from "../utils";

const priv = "99053a6568a93b9f194ef983c84ddfa9eb2b37888e47433558d40b2f4770b2d8";
Expand All @@ -15,23 +15,15 @@ test("public key", () => {

test("sign", () => {
const signature = signEcdsa(msg, priv);
expect(signature).toEqual({
r: "d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c7",
s: "19d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f375",
v: 0
});
expect(signature).toEqual(
"d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c719d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f37500"
);
});

test("verify - success", () => {
const result = verifyEcdsa(
msg,
{
r:
"d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c7",
s:
"19d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f375",
v: 0
},
"d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c719d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f37500",
getPublicFromPrivate(priv)
);
expect(result).toBe(true);
Expand All @@ -40,23 +32,16 @@ test("verify - success", () => {
test("verify - fail", () => {
const result = verifyEcdsa(
"0000000000000000000000000000000000000000000000000000000000000000",
{
r:
"d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c7",
s:
"19d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f375",
v: 0
},
"d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c719d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f37500",
getPublicFromPrivate(priv)
);
expect(result).toBe(false);
});

test("recover", () => {
const a = recoverEcdsa(msg, {
r: "d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c7",
s: "19d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f375",
v: 0
});
const a = recoverEcdsa(
msg,
"d8706a863775325b1b8c3f16c19ff337c2699c4f857be903e08a5a9234c5a5c719d685ae28e52081480b08a3a1e5d8dd1f852b78f65a7e99af37ad42ebc5f37500"
);
expect(a).toBe(getPublicFromPrivate(priv));
});
89 changes: 16 additions & 73 deletions src/core/SignedTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { H160, H256, H512, PlatformAddress, U256 } from "codechain-primitives";
import { H160, H256, H512, PlatformAddress } from "codechain-primitives";
import * as _ from "lodash";

import { blake160, blake256, recoverEcdsa } from "../utils";
Expand All @@ -24,64 +24,30 @@ const RLP = require("rlp");
* - A seq is not identical to the signer's seq.
*/
export class SignedTransaction {
/**
* Convert r, s, v values of an ECDSA signature to a string.
* @param params.r The r value of an ECDSA signature, which is up to 32 bytes of hexadecimal string.
* @param params.s The s value of an ECDSA signature, which is up to 32 bytes of hexadecimal string.
* @param params.v The recovery parameter of an ECDSA signature.
* @returns A 65 byte hexadecimal string.
*/
public static convertRsvToSignatureString(params: {
r: string;
s: string;
v: number;
}) {
const { r, s, v } = params;
return `0x${_.padStart(r, 64, "0")}${_.padStart(
s,
64,
"0"
)}${_.padStart(v.toString(16), 2, "0")}`;
}

private static convertSignatureStringToRsv(
signature: string
): { r: string; s: string; v: number } {
if (signature.startsWith("0x")) {
signature = signature.substr(2);
}
const r = `0x${signature.substr(0, 64)}`;
const s = `0x${signature.substr(64, 64)}`;
const v = Number.parseInt(signature.substr(128, 2), 16);
return { r, s, v };
}
public unsigned: Transaction;
public v: number;
public r: U256;
public s: U256;
public blockNumber: number | null;
public blockHash: H256 | null;
public transactionIndex: number | null;
private _signature: string;

/**
* @param unsigned A Transaction.
* @param sig An ECDSA signature which is a 65 byte hexadecimal string.
* @param signature An ECDSA signature which is a 65 byte hexadecimal string.
* @param blockNumber The block number of the block that contains the tx.
* @param blockHash The hash of the block that contains the tx.
* @param transactionIndex The index(location) of the tx within the block.
*/
constructor(
unsigned: Transaction,
sig: string,
signature: string,
blockNumber?: number,
blockHash?: H256,
transactionIndex?: number
) {
this.unsigned = unsigned;
const { r, s, v } = SignedTransaction.convertSignatureStringToRsv(sig);
this.v = v;
this.r = new U256(r);
this.s = new U256(s);
this._signature = signature.startsWith("0x")
? signature.substr(2)
: signature;
this.blockNumber = blockNumber === undefined ? null : blockNumber;
this.blockHash = blockHash || null;
this.transactionIndex =
Expand All @@ -92,22 +58,16 @@ export class SignedTransaction {
* Get the signature of a tx.
*/
public signature() {
const { v, r, s } = this;
return { v, r, s };
return this._signature;
}

/**
* Convert to an object for RLP encoding.
*/
public toEncodeObject(): any[] {
const { unsigned, v, r, s } = this;
const sig = `0x${_.padStart(r.value.toString(16), 64, "0")}${_.padStart(
s.value.toString(16),
64,
"0"
)}${_.padStart(v.toString(16), 2, "0")}`;
const { unsigned, _signature } = this;
const result = unsigned.toEncodeObject();
result.push(sig);
result.push(`0x${_signature}`);
return result;
}

Expand Down Expand Up @@ -137,12 +97,8 @@ export class SignedTransaction {
* @deprecated
*/
public getSignerAccountId(): H160 {
const { r, s, v, unsigned } = this;
const publicKey = recoverEcdsa(unsigned.hash().value, {
r: r.value.toString(16),
s: s.value.toString(16),
v
});
const { _signature, unsigned } = this;
const publicKey = recoverEcdsa(unsigned.hash().value, _signature);
return new H160(blake160(publicKey));
}

Expand All @@ -160,14 +116,8 @@ export class SignedTransaction {
* @returns A public key.
*/
public getSignerPublic(): H512 {
const { r, s, v, unsigned } = this;
return new H512(
recoverEcdsa(unsigned.hash().value, {
r: r.value.toString(16),
s: s.value.toString(16),
v
})
);
const { _signature, unsigned } = this;
return new H512(recoverEcdsa(unsigned.hash().value, _signature));
}

/**
Expand All @@ -180,20 +130,13 @@ export class SignedTransaction {
blockHash,
transactionIndex,
unsigned,
v,
r,
s
_signature
} = this;
const sig = SignedTransaction.convertRsvToSignatureString({
r: r.value.toString(16),
s: s.value.toString(16),
v
});
const result = unsigned.toJSON();
result.blockNumber = blockNumber;
result.blockHash = blockHash === null ? null : blockHash.toJSON();
result.transactionIndex = transactionIndex;
result.sig = sig;
result.sig = `0x${_signature}`;
result.hash = this.hash().toJSON();
return result;
}
Expand Down
8 changes: 3 additions & 5 deletions src/core/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,10 @@ export abstract class Transaction {
throw Error("The tx fee is already set");
}
this._fee = U64.ensure(fee);
const { r, s, v } = signEcdsa(
this.hash().value,
H256.ensure(secret).value
return new SignedTransaction(
this,
signEcdsa(this.hash().value, H256.ensure(secret).value)
);
const sig = SignedTransaction.convertRsvToSignatureString({ r, s, v });
return new SignedTransaction(this, sig);
}

public toJSON() {
Expand Down
13 changes: 2 additions & 11 deletions src/core/__test__/Transaction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,8 @@ test("sign", () => {
seq: 0,
fee: 0
});
const { v, r, s } = signed.signature();
expect(v).toBe(1);
expect(r.toEncodeObject()).toEqual(
new U256(
"0x3f9bcff484bd5f1d5549f912f9eeaf8c2fe349b257bde2b61fb1036013d4e44c"
).toEncodeObject()
);
expect(s.toEncodeObject()).toEqual(
new U256(
"0x204a4215d26cb879eaad2028fe1a7898e4cf9a5d979eb383e0a384140d6e04c1"
).toEncodeObject()
expect(signed.signature()).toBe(
"3f9bcff484bd5f1d5549f912f9eeaf8c2fe349b257bde2b61fb1036013d4e44c204a4215d26cb879eaad2028fe1a7898e4cf9a5d979eb383e0a384140d6e04c101"
);
});

Expand Down
7 changes: 1 addition & 6 deletions src/core/transaction/Remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,7 @@ export class Remove extends Transaction {
if ("secret" in params) {
const { hash, secret } = params;
this._hash = hash;
const { r, s, v } = signEcdsa(hash.value, secret.value);
this.signature = `${_.padStart(r, 64, "0")}${_.padStart(
s,
64,
"0"
)}${_.padStart(v.toString(16), 2, "0")}`;
this.signature = signEcdsa(hash.value, secret.value);
} else {
let signature = params.signature;
if (signature.startsWith("0x")) {
Expand Down
7 changes: 1 addition & 6 deletions src/core/transaction/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,10 @@ export class Store extends Transaction {
getPublicFromPrivate(secret.value),
{ networkId }
);
const { r, s, v } = signEcdsa(
this.signature = signEcdsa(
blake256(RLP.encode(content)),
secret.value
);
this.signature = `${_.padStart(r, 64, "0")}${_.padStart(
s,
64,
"0"
)}${_.padStart(v.toString(16), 2, "0")}`;
} else {
const { content, certifier } = params;
let signature = params.signature;
Expand Down
8 changes: 1 addition & 7 deletions src/key/MemoryKeyStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,7 @@ class KeyManager implements KeyManagementAPI {
if (passphrase !== this.passphraseMap[key]) {
return Promise.reject("The passphrase does not match");
}
const { r, s, v } = signEcdsa(message, this.privateKeyMap[key]);
const sig = `${_.padStart(r, 64, "0")}${_.padStart(
s,
64,
"0"
)}${_.padStart(v.toString(16), 2, "0")}`;
return Promise.resolve(sig);
return Promise.resolve(signEcdsa(message, this.privateKeyMap[key]));
}
}

Expand Down
8 changes: 2 additions & 6 deletions src/key/__test__/LocalKeyStore.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ test("sign", async () => {
key,
message
});
const r = `${signature.substr(0, 64)}`;
const s = `${signature.substr(64, 64)}`;
const v = Number.parseInt(signature.substr(128, 2), 16);

expect(verifyEcdsa(message, { r, s, v }, publicKey)).toBe(true);
expect(recoverEcdsa(message, { r, s, v })).toEqual(publicKey);
expect(verifyEcdsa(message, signature, publicKey)).toBe(true);
expect(recoverEcdsa(message, signature)).toEqual(publicKey);
});
14 changes: 5 additions & 9 deletions src/key/__test__/MemoryKeyStore.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
recoverEcdsa,
verifyEcdsa,
getAccountIdFromPublic,
getPublicFromPrivate,
getAccountIdFromPublic
recoverEcdsa,
verifyEcdsa
} from "../../utils";
import { MemoryKeyStore } from "../MemoryKeyStore";

Expand Down Expand Up @@ -53,10 +53,6 @@ test("sign", async () => {
key,
message
});
const r = `${signature.substr(0, 64)}`;
const s = `${signature.substr(64, 64)}`;
const v = Number.parseInt(signature.substr(128, 2), 16);

expect(verifyEcdsa(message, { r, s, v }, publicKey)).toBe(true);
expect(recoverEcdsa(message, { r, s, v })).toEqual(publicKey);
expect(verifyEcdsa(message, signature, publicKey)).toBe(true);
expect(recoverEcdsa(message, signature)).toEqual(publicKey);
});
Loading