From 8815a6e78989e8fde6edabdbb41c2742b133c14e Mon Sep 17 00:00:00 2001 From: meetsiraja Date: Wed, 20 Nov 2019 15:49:24 +0530 Subject: [PATCH] Sign Transaction with ethereum account private key --- src/middleware/signed-tx-middleware.ts | 40 +++++++++++++++++++------- src/solidity-helpers.ts | 21 ++++++-------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/middleware/signed-tx-middleware.ts b/src/middleware/signed-tx-middleware.ts index 421d257c..5f873546 100644 --- a/src/middleware/signed-tx-middleware.ts +++ b/src/middleware/signed-tx-middleware.ts @@ -1,28 +1,46 @@ +import debug from 'debug' import { SignedTx } from '../proto/loom_pb' import { ITxMiddlewareHandler } from '../client' -import { sign, publicKeyFromPrivateKey } from '../crypto-utils' +import { OfflineWeb3Signer, soliditySha3 } from '../solidity-helpers' +import { bytesToHex, hexToBytes } from '../crypto-utils' +import Web3 from 'web3' + +const log = debug('signed-tx-middleware') /** * Signs transactions. */ export class SignedTxMiddleware implements ITxMiddlewareHandler { // The private key that should be used to sign txs. - privateKey: Uint8Array + private _web3: Web3 + private _account: any /** - * Creates middlware that signs txs with the given key. - * @param privateKey The private key that should be used to sign txs. + * @param web3 Web3 instance to use for signing. + * @param account Web3 account to sign with. */ - constructor(privateKey: Uint8Array) { - this.privateKey = privateKey + constructor(web3: Web3, account: any) { + this._web3 = web3 + this._account = account } - Handle(txData: Readonly): Promise { - const sig = sign(txData as Uint8Array, this.privateKey) + async Handle(txData: Readonly): Promise { + // Get hash to be signed + const hash = soliditySha3({ + type: 'bytes', + value: bytesToHex(txData) + }) + + // Signing the transaction + const offlineSigner = new OfflineWeb3Signer(this._web3, this._account) + const sig = await offlineSigner.signAsync(hash) + + log(`signer: ${this._account.address}, signature: 0x${bytesToHex(sig.slice(1))}`) + const signedTx = new SignedTx() signedTx.setInner(txData as Uint8Array) signedTx.setSignature(sig) - signedTx.setPublicKey(publicKeyFromPrivateKey(this.privateKey)) - return Promise.resolve(signedTx.serializeBinary()) + + return signedTx.serializeBinary() } -} +} \ No newline at end of file diff --git a/src/solidity-helpers.ts b/src/solidity-helpers.ts index 343825d3..e2f2a378 100644 --- a/src/solidity-helpers.ts +++ b/src/solidity-helpers.ts @@ -136,18 +136,13 @@ export class OfflineWeb3Signer implements IEthereumSigner { * @returns Promise that will be resolved with the signature bytes. */ async signAsync(msg: string): Promise { - const ret = await this._web3.eth.accounts.sign(msg, this._account.privateKey) - // @ts-ignore - const sig = ret.signature.slice(2) - const r = ethutil.toBuffer('0x' + sig.substring(0, 64)) as Buffer - const s = ethutil.toBuffer('0x' + sig.substring(64, 128)) as Buffer - let v = parseInt(sig.substring(128, 130), 16) - - return Buffer.concat([ - ethutil.toBuffer(SIGNATURE_TYPE.GETH) as Buffer, - r, - s, - ethutil.toBuffer(v) as Buffer - ]) + let flatSig = await this._web3.eth.accounts.sign(msg, this._account.privateKey) + const sig = ethers.utils.splitSignature(flatSig) + let v = sig.v! + if (v === 0 || v === 1) { + v += 27 + } + flatSig = '0x01' + sig.r.slice(2) + sig.s.slice(2) + v.toString(16) + return ethutil.toBuffer(flatSig) } }