안녕하세요? caver의 account와 wallet.keyring 관련 테스트 하는 중에 난관에 봉착하여 이렇게 문의 드립니다.
테스트 하고자 하는 내용은 아래와 같습니다.
single keyring 2개를 생성하여 해당 key값 (key1, key2)으로 multiple keyring 하나 생성
multiple keyring address로 다른 주소에게 klay를 송금하는 transaction 생성
생성한 transaction에 대한 서명을 key1으로 수행해봄
생성한 transaction에 대한 서명을 key2로 수행해봄
multiple keyring address는 첫번째 single keyring의 address (key1의 address)로 하였습니다.
수행 결과 key1으로 수행 시 정상동작 합니다.
key2로 수행하면 아래와 같은 에러가 발생합니다.
Error: The from address of the transaction is different with the address of the keyring to use.
at ValueTransfer.sign (/Users/hongjonghyeon/klaytn/programs/ex-caverjs/node_modules/caver-js/packages/caver-transaction/src/transactionTypes/abstractTransaction.js:200:19)
at testFunc (/Users/hongjonghyeon/klaytn/programs/ex-caverjs/exams/ExamCaverWallet.js:155:18)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async RunProc (/Users/hongjonghyeon/klaytn/programs/ex-caverjs/exams/ExamCaverWallet.js:236:9)
kscn 콘솔에서 klay.getAccount 명령으로 생성한 multi keyring의 주소를 조회해보니 아래와 같았습니다.
안녕하세요.
처음 생성한 계정의 account key는 AccountKeyLegacy입니다.
멀티시그를 사용하기 위해서는 이를 AccountKeyWeightedMultiSig로 업데이트 해주어야 합니다.
업데이트 하기 위해서는 AccountUpdate 트랜잭션을 네트워크에 전송해야 합니다.
// test.js
const Caver = require('caver-js')
const caver = new Caver('https://your.en.url:8651/')
async function testFunction() {
// 아래 sender가 업데이트할 계정입니다. KLAY를 소유하고 있어야 합니다.
let sender = caver.wallet.keyring.createFromPrivateKey('0x{private key}')
caver.wallet.add(sender)
// Create an account instance with three private keys using AccountKeyWeightedMultiSig
const newPrivateKeys = caver.wallet.keyring.generateMultipleKeys(3)
// 아래의 키링이 새롭게 사용할 private keys를 갖고 있는 키링입니다. 이를 사용하여 업데이트에 필요한 오브젝트를 만들고, 업데이트가 모두 완료된 이후 `caver.wallet.updateKeyring`을 사용하여 sender.address 에서 사용하는 키를 업데이트 하면 됩니다.
const newKeyring = caver.wallet.keyring.createWithMultipleKey(sender.address, newPrivateKeys)
// threshold = 3, the weights of the three keys = [1, 2, 1]
const options = new caver.account.weightedMultiSigOptions(3, [1, 2, 1])
const account = newKeyring.toAccount(options)
const updateTx = caver.transaction.accountUpdate.create({
from: sender.address,
account: account,
gas: 50000,
})
await caver.wallet.sign(sender.address, updateTx)
const receipt = await caver.rpc.klay.sendRawTransaction(updateTx)
console.log(receipt)
// Update the keyring in caver.wallet for signing afterward.
sender = caver.wallet.updateKeyring(newKeyring)
}
testFunction()
reference 주신 예제 코드에서 가중치 부여하는 옵션 코드를 제거하여 threshold: 1이 되도록 했습니다. 한번만 서명하면 transaction이 발행될 수 있도록이요.
이후 KLAY 전송을 위해 multiple keyring 을 구성하는 private key들로 서명을 해봤는데 모두 다 아래의 에러코드를 반환하며 실패했습니다.
Error: The from address of the transaction is different with the address of the keyring to use.
at ValueTransfer.sign (/Users/hongjonghyeon/klaytn/programs/ex-caverjs/node_modules/caver-js/packages/caver-transaction/src/transactionTypes/abstractTransaction.js:200:19)
at testFunc (/Users/hongjonghyeon/klaytn/programs/ex-caverjs/exams/ExamCaverWallet.js:264:18)
at RunProc (/Users/hongjonghyeon/klaytn/programs/ex-caverjs/exams/ExamCaverWallet.js:324:15)
at Object. (/Users/hongjonghyeon/klaytn/programs/ex-caverjs/exams/ExamCaverWallet.js:329:1)
at Module._compile (internal/modules/cjs/loader.js:1068:30)
at Object.Module._extensions…js (internal/modules/cjs/loader.js:1097:10)
at Module.load (internal/modules/cjs/loader.js:933:32)
at Function.Module._load (internal/modules/cjs/loader.js:774:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47
아래는 KLAY 전송코드 원문입니다.
let testFunc = async function() {
try {
let fromAddr = “0x2317816e54c5066a1106a202c6304d9a39d03e5b”; // 생성한 multikeyring의 address
let toAddr = “0x7b3f9ff0f4215c41b3e4a49510b540e80d0c790b”; // test용 주소
let amount = “1000000000000000000”; // 1 Klay
let rawTx = {
from: fromAddr,
to: toAddr,
gas: 25000,
value: amount};
//let privKey = keyring.keys[0].privateKey;
let privKey = “0x7bb3ca9638974d9bea2656780d2033e79b1291b58c1bbc3e655f436bd84ca198”; // multikeyring의 private key들을 번갈아 넣어봤습니다.
console.log(privKey)
const tx = caver.transaction.valueTransfer.create(rawTx);
await tx.sign(privKey);
await caver.rpc.klay.sendRawTransaction(tx)
질문 하나만 더 올리겠습니다. (__)
RoleBased Keyring에서도 Multiple Keyring과 동일한 방식인지요?
즉
각 역할을 수행할 private key들을 생성하여 RoleBased Keyring이 생성되면
이를 Wallet에 등록해두고
일반 transaction 서명이든, Account Update 서명이든 Fee Payer 서명이든 동일하게
caver.wallet.sign(address, rawTransaction) 으로 서명하는 개념인가요?