Skip to content

Commit

Permalink
Add transaction replay protection
Browse files Browse the repository at this point in the history
  • Loading branch information
bowenwang1996 authored and ilblackdragon committed Aug 28, 2019
1 parent 4a9a8eb commit 841e215
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 10 deletions.
3 changes: 2 additions & 1 deletion lib/account.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/transaction.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions lib/transaction.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions src.ts/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Action, transfer, createAccount, signTransaction, deployContract,
addKey, functionCall, fullAccessKey, functionCallAccessKey, deleteKey, stake, AccessKey } from './transaction';
import { FinalTransactionResult, FinalTransactionStatus } from './providers/provider';
import { Connection } from './connection';
import { base_encode } from './utils/serialize';
import {base_decode, base_encode} from './utils/serialize';

// Default amount of tokens to be send with the function calls. Used to pay for the fees
// incurred while running the contract execution. The unused amount will be refunded back to
Expand Down Expand Up @@ -90,8 +90,12 @@ export class Account {
if (this._accessKey === null) {
throw new Error(`Can not sign transactions, initialize account with available public key in Signer.`);
}

let status = await this.connection.provider.status();

const [txHash, signedTx] = await signTransaction(
receiverId, ++this._accessKey.nonce, actions, this.connection.signer, this.accountId, this.connection.networkId);
receiverId, ++this._accessKey.nonce, actions, base_decode(status.sync_info.latest_block_hash), this.connection.signer, this.accountId, this.connection.networkId
);

let result;
try {
Expand Down
7 changes: 4 additions & 3 deletions src.ts/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Transaction extends Assignable {
nonce: number;
receiverId: string;
actions: Action[];
blockHash: Uint8Array;
}

export class SignedTransaction extends Assignable {
Expand All @@ -152,7 +153,7 @@ export class Action extends Enum {
const SCHEMA = new Map<Function, any>([
[Signature, {kind: 'struct', fields: [['keyType', 'u8'], ['data', [32]]]}],
[SignedTransaction, {kind: 'struct', fields: [['transaction', Transaction], ['signature', Signature]]}],
[Transaction, { kind: 'struct', fields: [['signerId', 'string'], ['publicKey', PublicKey], ['nonce', 'u64'], ['receiverId', 'string'], ['actions', [Action]]] }],
[Transaction, { kind: 'struct', fields: [['signerId', 'string'], ['publicKey', PublicKey], ['nonce', 'u64'], ['receiverId', 'string'], ['blockHash', [32]], ['actions', [Action]]] }],
[PublicKey, {
kind: 'struct', fields: [['keyType', 'u8'], ['data', [32]]] }],
[AccessKey, { kind: 'struct', fields: [
Expand Down Expand Up @@ -189,9 +190,9 @@ const SCHEMA = new Map<Function, any>([
[DeleteAccount, { kind: 'struct', fields: [['beneficiaryId', 'string']] }],
]);

export async function signTransaction(receiverId: string, nonce: number, actions: Action[], signer: Signer, accountId?: string, networkId?: string): Promise<[Uint8Array, SignedTransaction]> {
export async function signTransaction(receiverId: string, nonce: number, actions: Action[], blockHash: Uint8Array, signer: Signer, accountId?: string, networkId?: string): Promise<[Uint8Array, SignedTransaction]> {
const publicKey = new PublicKey(await signer.getPublicKey(accountId, networkId));
const transaction = new Transaction({ signerId: accountId, publicKey, nonce, receiverId, actions });
const transaction = new Transaction({ signerId: accountId, publicKey, nonce, receiverId, actions, blockHash });
const message = serialize(SCHEMA, transaction);
const hash = new Uint8Array(sha256.sha256.array(message));
const signature = await signer.signHash(hash, accountId, networkId);
Expand Down

0 comments on commit 841e215

Please sign in to comment.