From 8296df6fe7a4a7c8a8c464748abef49ba143d2d0 Mon Sep 17 00:00:00 2001 From: Nohyun Nehemiah Kwak Date: Thu, 7 Sep 2023 16:25:29 +0900 Subject: [PATCH 1/3] Check RLP in each functions --- ...ntKeyWeightedMultiSig_02_valueTransfer2.js | 50 +++++++++++++++ ethers-ext/src/ethers/signer.ts | 62 ++++++++++--------- 2 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js diff --git a/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js b/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js new file mode 100644 index 000000000..143a400d9 --- /dev/null +++ b/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js @@ -0,0 +1,50 @@ +const { Wallet, TxType, parseKlay } = require("@klaytn/ethers-ext"); +const ethers = require("ethers"); + +// +// AccountKeyWeightedMultiSig Step 02 - value transfer +// https://docs.klaytn.foundation/content/klaytn/design/accounts#accountkeyweightedmultisig +// +// gasLimit: Must be large enough +// + +const provider = new ethers.providers.JsonRpcProvider("https://public-en-baobab.klaytn.net"); + +// the same address of sender in AccountKeyWeightedMultiSig_01_accountUpdate.js +const recieverAddr = "0xc40b6909eb7085590e1c26cb3becc25368e249e9"; +const senderAddr = "0x82c6a8d94993d49cfd0c1d30f0f8caa65782cc7e"; +const senderNewPriv1 = "0xa32c30608667d43be2d652bede413f12a649dd1be93440878e7f712d51a6768a"; +const senderNewPriv2 = "0x0e4ca6d38096ad99324de0dde108587e5d7c600165ae4cd6c2462c597458c2b8"; +const senderNewPriv3 = "0xc9668ccd35fc20587aa37a48838b48ccc13cf14dd74c8999dd6a480212d5f7ac"; + +async function main() { + let tx = { + type: TxType.ValueTransfer, + gasLimit: 100000, + to: recieverAddr, + value: parseKlay("1"), + from: senderAddr, + }; + + // sign 1 + const wallet = new Wallet(senderAddr, senderNewPriv1, provider); + let ptx = await wallet.populateTransaction(tx); + const txHashRLP = await wallet.signTransaction(ptx); + console.log("TxHashRLP", txHashRLP); + + // sign 2 + const wallet2 = new Wallet(senderAddr, senderNewPriv2, provider); + let ptx2 = await wallet2.populateTransaction(txHashRLP); + const txHashRLP2 = await wallet2.signTransaction(ptx2); + console.log("TxHashRLP2", txHashRLP2); + + // sign 3 & send + const wallet3 = new Wallet(senderAddr, senderNewPriv3, provider); + const res = await wallet3.sendTransaction(txHashRLP2); + console.log("transaction", res); + + const rc = await provider.waitForTransaction(res.hash); + console.log("receipt", rc); +} + +main(); diff --git a/ethers-ext/src/ethers/signer.ts b/ethers-ext/src/ethers/signer.ts index 35fa8bf31..5800687de 100644 --- a/ethers-ext/src/ethers/signer.ts +++ b/ethers-ext/src/ethers/signer.ts @@ -102,9 +102,22 @@ export class Wallet extends EthersWallet { return tx; } - async populateTransaction(transaction: Deferrable): Promise { - let tx: TransactionRequest = await resolveProperties(transaction); + convertTxFromRLP(transaction: Deferrable | string): any { + if (typeof transaction === "string") { + if (HexStr.isHex(transaction)) { + return this.decodeTxFromRLP(transaction); + } else { + throw new Error("String type input has to be RLP encoded Hex string."); + } + } else { + return transaction; + } + } + async populateTransaction(transaction: Deferrable): Promise { + let tx: TransactionRequest = this.convertTxFromRLP(transaction); + tx = await resolveProperties(tx); + if (!KlaytnTxFactory.has(tx.type)) { return super.populateTransaction(tx); } @@ -172,8 +185,9 @@ export class Wallet extends EthersWallet { } async signTransaction(transaction: Deferrable): Promise { - const tx: TransactionRequest = await resolveProperties(transaction); - + let tx: TransactionRequest = this.convertTxFromRLP(transaction); + tx = await resolveProperties(tx); + if (!KlaytnTxFactory.has(tx.type)) { return super.signTransaction(tx); } @@ -194,18 +208,15 @@ export class Wallet extends EthersWallet { } async signTransactionAsFeePayer(transaction: Deferrable): Promise { - let tx = transaction; - if (typeof transaction === "string") { - if (HexStr.isHex(transaction)) { - tx = this.decodeTxFromRLP(transaction); - // @ts-ignore : we have to add feePayer property - tx.chainId = Math.floor((tx.txSignatures[0][0] - 35) / 2); - } else { - throw new Error("Input parameter has to be RLP encoded Hex string."); - } + let tx: TransactionRequest = this.convertTxFromRLP(transaction); + + // @ts-ignore : chainId can be omitted from RLP encoded format + if (!tx.chainId) { + // @ts-ignore + tx.chainId = this.getChainId(); } - const rtx: TransactionRequest = await resolveProperties(tx); + // @ts-ignore : we have to add feePayer property if (!rtx.feePayer) { // @ts-ignore : we have to add feePayer property @@ -232,10 +243,12 @@ export class Wallet extends EthersWallet { async sendTransaction(transaction: Deferrable): Promise { this._checkProvider("sendTransaction"); - const tx = await this.populateTransaction(transaction); - const signedTx = await this.signTransaction(tx); - if (!KlaytnTxFactory.has(tx.type)) { + let tx: TransactionRequest = this.convertTxFromRLP(transaction); + let ptx = await this.populateTransaction(tx); + const signedTx = await this.signTransaction(ptx); + + if (!KlaytnTxFactory.has(ptx.type)) { return await this.provider.sendTransaction(signedTx); } @@ -251,18 +264,11 @@ export class Wallet extends EthersWallet { async sendTransactionAsFeePayer(transaction: Deferrable | string): Promise { this._checkProvider("sendTransactionAsFeePayer"); - let tx, ptx; - if (typeof transaction === "string") { - if (HexStr.isHex(transaction)) { - tx = this.decodeTxFromRLP(transaction); - ptx = await this.populateTransaction(tx); - } else { - throw new Error("Input parameter has to be RLP encoded Hex string."); - } - } else { - ptx = await this.populateTransaction(transaction); - } + let tx: TransactionRequest = this.convertTxFromRLP(transaction); + let ptx = await this.populateTransaction(tx); + // @ts-ignore : we have to add feePayer property + ptx.feePayer = await this.getAddress(); const signedTx = await this.signTransactionAsFeePayer(ptx); if (this.provider instanceof EthersJsonRpcProvider) { From 4d2cb15937706928156030bf1bdb9c66714b8fd0 Mon Sep 17 00:00:00 2001 From: Nohyun Nehemiah Kwak Date: Thu, 7 Sep 2023 18:11:53 +0900 Subject: [PATCH 2/3] Rename _convertTxFromRLP --- ethers-ext/src/ethers/signer.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ethers-ext/src/ethers/signer.ts b/ethers-ext/src/ethers/signer.ts index 5800687de..a79f785c8 100644 --- a/ethers-ext/src/ethers/signer.ts +++ b/ethers-ext/src/ethers/signer.ts @@ -102,7 +102,7 @@ export class Wallet extends EthersWallet { return tx; } - convertTxFromRLP(transaction: Deferrable | string): any { + _convertTxFromRLP(transaction: Deferrable | string): any { if (typeof transaction === "string") { if (HexStr.isHex(transaction)) { return this.decodeTxFromRLP(transaction); @@ -115,7 +115,7 @@ export class Wallet extends EthersWallet { } async populateTransaction(transaction: Deferrable): Promise { - let tx: TransactionRequest = this.convertTxFromRLP(transaction); + let tx: TransactionRequest = this._convertTxFromRLP(transaction); tx = await resolveProperties(tx); if (!KlaytnTxFactory.has(tx.type)) { @@ -185,7 +185,7 @@ export class Wallet extends EthersWallet { } async signTransaction(transaction: Deferrable): Promise { - let tx: TransactionRequest = this.convertTxFromRLP(transaction); + let tx: TransactionRequest = this._convertTxFromRLP(transaction); tx = await resolveProperties(tx); if (!KlaytnTxFactory.has(tx.type)) { @@ -208,7 +208,7 @@ export class Wallet extends EthersWallet { } async signTransactionAsFeePayer(transaction: Deferrable): Promise { - let tx: TransactionRequest = this.convertTxFromRLP(transaction); + let tx: TransactionRequest = this._convertTxFromRLP(transaction); // @ts-ignore : chainId can be omitted from RLP encoded format if (!tx.chainId) { @@ -244,7 +244,7 @@ export class Wallet extends EthersWallet { async sendTransaction(transaction: Deferrable): Promise { this._checkProvider("sendTransaction"); - let tx: TransactionRequest = this.convertTxFromRLP(transaction); + let tx: TransactionRequest = this._convertTxFromRLP(transaction); let ptx = await this.populateTransaction(tx); const signedTx = await this.signTransaction(ptx); @@ -264,7 +264,7 @@ export class Wallet extends EthersWallet { async sendTransactionAsFeePayer(transaction: Deferrable | string): Promise { this._checkProvider("sendTransactionAsFeePayer"); - let tx: TransactionRequest = this.convertTxFromRLP(transaction); + let tx: TransactionRequest = this._convertTxFromRLP(transaction); let ptx = await this.populateTransaction(tx); // @ts-ignore : we have to add feePayer property From fe61fbfce6aa098937f3ea1c0309c5c8abf3b6ae Mon Sep 17 00:00:00 2001 From: Nohyun Nehemiah Kwak Date: Thu, 7 Sep 2023 18:12:13 +0900 Subject: [PATCH 3/3] Update example --- ...untKeyWeightedMultiSig_02_valueTransfer.js | 22 ++------ ...ntKeyWeightedMultiSig_02_valueTransfer2.js | 50 ------------------- 2 files changed, 5 insertions(+), 67 deletions(-) delete mode 100644 ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js diff --git a/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer.js b/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer.js index 94a384a6e..fe8c053da 100644 --- a/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer.js +++ b/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer.js @@ -34,28 +34,16 @@ async function main() { // sign 2 const wallet2 = new Wallet(senderAddr, senderNewPriv2, provider); - let decodedTx = wallet2.decodeTxFromRLP(txHashRLP); - console.log(decodedTx); - let ptx2 = await wallet2.populateTransaction(decodedTx); + let ptx2 = await wallet2.populateTransaction(txHashRLP); const txHashRLP2 = await wallet2.signTransaction(ptx2); console.log("TxHashRLP2", txHashRLP2); - // sign 3 + // sign 3 & send const wallet3 = new Wallet(senderAddr, senderNewPriv3, provider); - let decodedTx2 = wallet3.decodeTxFromRLP(txHashRLP2); - console.log(decodedTx2); - let ptx3 = await wallet3.populateTransaction(decodedTx2); - const txHashRLP3 = await wallet3.signTransaction(ptx3); - console.log("TxHashRLP3", txHashRLP3); + const res = await wallet3.sendTransaction(txHashRLP2); + console.log("transaction", res); - let decodedTx3 = wallet3.decodeTxFromRLP(txHashRLP3); - console.log(decodedTx3); - - // send - const txhash = await provider.send("klay_sendRawTransaction", [txHashRLP3]); - console.log("txhash", txhash); - - const rc = await provider.waitForTransaction(txhash); + const rc = await res.wait(); console.log("receipt", rc); } diff --git a/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js b/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js deleted file mode 100644 index 143a400d9..000000000 --- a/ethers-ext/example/accountKey/AccountKeyWeightedMultiSig_02_valueTransfer2.js +++ /dev/null @@ -1,50 +0,0 @@ -const { Wallet, TxType, parseKlay } = require("@klaytn/ethers-ext"); -const ethers = require("ethers"); - -// -// AccountKeyWeightedMultiSig Step 02 - value transfer -// https://docs.klaytn.foundation/content/klaytn/design/accounts#accountkeyweightedmultisig -// -// gasLimit: Must be large enough -// - -const provider = new ethers.providers.JsonRpcProvider("https://public-en-baobab.klaytn.net"); - -// the same address of sender in AccountKeyWeightedMultiSig_01_accountUpdate.js -const recieverAddr = "0xc40b6909eb7085590e1c26cb3becc25368e249e9"; -const senderAddr = "0x82c6a8d94993d49cfd0c1d30f0f8caa65782cc7e"; -const senderNewPriv1 = "0xa32c30608667d43be2d652bede413f12a649dd1be93440878e7f712d51a6768a"; -const senderNewPriv2 = "0x0e4ca6d38096ad99324de0dde108587e5d7c600165ae4cd6c2462c597458c2b8"; -const senderNewPriv3 = "0xc9668ccd35fc20587aa37a48838b48ccc13cf14dd74c8999dd6a480212d5f7ac"; - -async function main() { - let tx = { - type: TxType.ValueTransfer, - gasLimit: 100000, - to: recieverAddr, - value: parseKlay("1"), - from: senderAddr, - }; - - // sign 1 - const wallet = new Wallet(senderAddr, senderNewPriv1, provider); - let ptx = await wallet.populateTransaction(tx); - const txHashRLP = await wallet.signTransaction(ptx); - console.log("TxHashRLP", txHashRLP); - - // sign 2 - const wallet2 = new Wallet(senderAddr, senderNewPriv2, provider); - let ptx2 = await wallet2.populateTransaction(txHashRLP); - const txHashRLP2 = await wallet2.signTransaction(ptx2); - console.log("TxHashRLP2", txHashRLP2); - - // sign 3 & send - const wallet3 = new Wallet(senderAddr, senderNewPriv3, provider); - const res = await wallet3.sendTransaction(txHashRLP2); - console.log("transaction", res); - - const rc = await provider.waitForTransaction(res.hash); - console.log("receipt", rc); -} - -main();