はじめに
こんにちは。
symbol-sdkの3系、トランザクションシリーズ第五弾です。
今回はマルチシグをやっていきます。
注意事項
書いてあるコードについて、正確性や完全性を保証するものではありません。あくまで参考程度として頂き、最新情報は公式ドキュメンテーションをご確認ください。
共通
まずは共通となる個所について。デッドラインと鍵ペアです。
import symbolSdk from 'symbol-sdk';
const network = symbolSdk.symbol.Network.TESTNET;
const deadline = network.fromDatetime(new Date(Date.now() + 7200000)).timestamp;
const facade = new symbolSdk.facade.SymbolFacade(network.name);
const privateKey = new symbolSdk.PrivateKey(PRIVATE_KEY);
const keyPair = new facade.constructor.KeyPair(privateKey);
XEMのモザイクIDも書いておきます。
const currencyMosaicId = 0x72C0212E67A08BCEn;
マルチシグアカウントを作成するにあたって、登場人物を3人用意します。
Alice, Bob, Carol です。それぞれ、ランダムな秘密鍵を生成します。
import crypto from 'crypto';
const alicePrivateKey = new symbolSdk.PrivateKey(crypto.randomBytes(32).toString('hex').toUpperCase());
const aliceKeyPair = new facade.constructor.KeyPair(alicePrivateKey);
const aliceAddress = network.publicKeyToAddress(aliceKeyPair.publicKey);
const bobPrivateKey = new symbolSdk.PrivateKey(crypto.randomBytes(32).toString('hex').toUpperCase());
const bobKeyPair = new facade.constructor.KeyPair(bobPrivateKey);
const bobAddress = network.publicKeyToAddress(bobKeyPair.publicKey);
const carolPrivateKey = new symbolSdk.PrivateKey(crypto.randomBytes(32).toString('hex').toUpperCase());
const carolKeyPair = new facade.constructor.KeyPair(carolPrivateKey);
const carolAddress = network.publicKeyToAddress(carolKeyPair.publicKey);
マルチシグ構成
事前準備
今回は、Alice がトランザクションの送信者(署名者)にする予定です。
そのためにはXEM残高が必要ですが、ランダム生成したアカウントなので残高ゼロです。
そこでXEMを少し送っておきます。
const fundTransaction = facade.transactionFactory.create({
type: 'transfer_transaction_v1',
signerPublicKey: keyPair.publicKey.toString(),
fee: 1000000n,
deadline,
recipientAddress: aliceAddress,
mosaics: [
{ mosaicId: currencyMosaicId, amount: 1000000n },
],
});
const fundSignature = facade.signTransaction(keyPair, fundTransaction);
const fundJsonPayload = facade.transactionFactory.constructor.attachSignature(fundTransaction, fundSignature);
const fundHash = facade.hashTransaction(fundTransaction).toString();
const fundSendRes = await axios.put(`${NODE_INFO}/transactions`, fundJsonPayload).then((res) => res.data);
マルチシグ化
今回は、 Alice をマルチシグアカウントとし、Bob と Carol の 2 of 2 マルチシグを組みます。
そのためには、3人全員の署名が必要になります(確か)。
なのでまずは、マルチシグモディフィケーショントランザクションを作成し、
次に、アグリゲートコンプリートトランザクションでラップして全員の署名を付けていきます。
マルチシグモディフィケーショントランザクション
createEmbedded
を使うところに注意。
const innerTransaction1 = facade.transactionFactory.createEmbedded({
type: 'multisig_account_modification_transaction_v1',
signerPublicKey: aliceKeyPair.publicKey,
minRemovalDelta: 2,
minApprovalDelta: 2,
addressAdditions: [ bobAddress, carolAddress ],
addressDeletions: [],
});
アグリゲートコンプリートトランザクション
const innerTransactions = [ innerTransaction1 ];
const transactionsHash = symbolSdk.facade.SymbolFacade.hashEmbeddedTransactions(innerTransactions);
const transaction = facade.transactionFactory.create({
type: 'aggregate_complete_transaction_v2',
signerPublicKey: aliceKeyPair.publicKey,
fee: 1000000n,
deadline,
transactions: innerTransactions,
transactionsHash,
});
署名とハッシュ計算
先に Alice の署名を行い、トランザクションハッシュを計算します。ここで、 attachSignature
の戻り値は破棄します。
const signature = facade.signTransaction(aliceKeyPair, transaction);
facade.transactionFactory.constructor.attachSignature(transaction, signature);
const hash = facade.hashTransaction(transaction).toString();
Bob と Carol の連署を作成し、トランザクションに取り込みます。
const bobCosignature = facade.cosignTransaction(bobKeyPair, transaction);
const carolCosignature = facade.cosignTransaction(carolKeyPair, transaction);
transaction.cosignatures.push(bobCosignature);
transaction.cosignatures.push(carolCosignature);
ここで、もう一度 attachSignature
を行い、トランザクションのペイロードを入手します。
const jsonPayload = facade.transactionFactory.constructor.attachSignature(transaction, signature);
送信
あとは、トランザクションを送信すれば、マルチシグ化が完了します。
const sendRes = await axios.put(`${NODE_URL}/transactions`, jsonPayload).then((res) => res.data);
console.log(sendRes);
おわりに
今回はマルチシグのトランザクションを作りました。
シリーズ