このガイドでは、複数のマルチシグアカウントを接続して、高度なチェーン上の承認ロジックを実現する方法について説明します。
マルチシグアカウント は他のマルチシグアカウントを連署者とすることができ、マルチシグトランザクションに “AND/OR” ロジックを追加できます。
このガイドでは、複雑な 3 階層マルチシグアカウント を作成します。
例えば、 アカウント #5 が アカウント #1 を含む AggregateBondedTransaction を開始する 場合、ブロックに取り込まれるためには、アカウント #7 または #8 および #4 がトランザクションに署名する必要があります。
マルチシグアカウントへの変換 ガイドを完了している
各マルチシグレベルの アカウント を作成する。
ルートマルチシグアカウントへ手数料を支払うために十分な symbol.xym
を入金してください。
マルチシグアカウント #2 の定義
// replace with network type
const networkType = NetworkType.TEST_NET;
// replace with private key
const multisig2PrivateKey =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const multisigAccount2 = Account.createFromPrivateKey(
multisig2PrivateKey,
networkType,
);
// replace with public key
const cosignatoryAccount5PublicKey =
'17E42BDF5B7FF5001DC96A262A1141FFBE3F09A3A45DE7C095AAEA14F45C0DA0';
const cosignatory5 = PublicAccount.createFromPublicKey(
cosignatoryAccount5PublicKey,
networkType,
);
// replace with public key
const cosignatoryAccount6PublicKey =
'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const cosignatory6 = PublicAccount.createFromPublicKey(
cosignatoryAccount6PublicKey,
networkType,
);
const convertMultisigAccount2Transaction = MultisigAccountModificationTransaction.create(
Deadline.create(epochAdjustment),
1,
1,
[cosignatory5.address, cosignatory6.address],
[],
networkType,
);
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with private key
const multisig2PrivateKey = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const multisigAccount2 = symbol_sdk_1.Account.createFromPrivateKey(multisig2PrivateKey, networkType);
// replace with public key
const cosignatoryAccount5PublicKey = '17E42BDF5B7FF5001DC96A262A1141FFBE3F09A3A45DE7C095AAEA14F45C0DA0';
const cosignatory5 = symbol_sdk_1.PublicAccount.createFromPublicKey(cosignatoryAccount5PublicKey, networkType);
// replace with public key
const cosignatoryAccount6PublicKey = 'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const cosignatory6 = symbol_sdk_1.PublicAccount.createFromPublicKey(cosignatoryAccount6PublicKey, networkType);
const convertMultisigAccount2Transaction = symbol_sdk_1.MultisigAccountModificationTransaction.create(symbol_sdk_1.Deadline.create(epochAdjustment), 1, 1, [cosignatory5.address, cosignatory6.address], [], networkType);
マルチシグアカウント #3 の定義
// replace with private key
const multisig3PrivateKey =
'1111111111111111111111111111111111111111111111111111111111111111';
const multisigAccount3 = Account.createFromPrivateKey(
multisig3PrivateKey,
networkType,
);
// replace with public key
const cosignatoryAccount7PublicKey =
'38C22255DE39952C5D18803EC305A888D5DDE2C59BF3D4EFFAE6FC5FFCBF4F5D';
const cosignatory7 = PublicAccount.createFromPublicKey(
cosignatoryAccount7PublicKey,
networkType,
);
// replace with public key
const cosignatoryAccount8PublicKey =
'9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA';
const cosignatory8 = PublicAccount.createFromPublicKey(
cosignatoryAccount8PublicKey,
networkType,
);
// replace with public key
const cosignatoryAccount4PublicKey =
'EB2B065D27C6A6FB322F2E568E1AAD9CD6C0F155675E2837058D4811F5C0247D';
const cosignatory4 = PublicAccount.createFromPublicKey(
cosignatoryAccount4PublicKey,
networkType,
);
const convertMultisigAccount3Transaction = MultisigAccountModificationTransaction.create(
Deadline.create(epochAdjustment),
2,
1,
[cosignatory7.address, cosignatory8.address, cosignatory4.address],
[],
networkType,
);
// replace with private key
const multisig3PrivateKey = '1111111111111111111111111111111111111111111111111111111111111111';
const multisigAccount3 = symbol_sdk_1.Account.createFromPrivateKey(multisig3PrivateKey, networkType);
// replace with public key
const cosignatoryAccount7PublicKey = '38C22255DE39952C5D18803EC305A888D5DDE2C59BF3D4EFFAE6FC5FFCBF4F5D';
const cosignatory7 = symbol_sdk_1.PublicAccount.createFromPublicKey(cosignatoryAccount7PublicKey, networkType);
// replace with public key
const cosignatoryAccount8PublicKey = '9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA';
const cosignatory8 = symbol_sdk_1.PublicAccount.createFromPublicKey(cosignatoryAccount8PublicKey, networkType);
// replace with public key
const cosignatoryAccount4PublicKey = 'EB2B065D27C6A6FB322F2E568E1AAD9CD6C0F155675E2837058D4811F5C0247D';
const cosignatory4 = symbol_sdk_1.PublicAccount.createFromPublicKey(cosignatoryAccount4PublicKey, networkType);
const convertMultisigAccount3Transaction = symbol_sdk_1.MultisigAccountModificationTransaction.create(symbol_sdk_1.Deadline.create(epochAdjustment), 2, 1, [cosignatory7.address, cosignatory8.address, cosignatory4.address], [], networkType);
マルチシグアカウント #1 の定義
// replace with private key
const multisig1PrivateKey =
'0000000000000000000000000000000000000000000000000000000000000000';
const multisigAccount1 = Account.createFromPrivateKey(
multisig1PrivateKey,
networkType,
);
const convertMultisigAccount1Transaction = MultisigAccountModificationTransaction.create(
Deadline.create(epochAdjustment),
3,
1,
[
multisigAccount2.publicAccount.address,
multisigAccount3.publicAccount.address,
cosignatory4.address,
],
[],
networkType,
);
// replace with private key
const multisig1PrivateKey = '0000000000000000000000000000000000000000000000000000000000000000';
const multisigAccount1 = symbol_sdk_1.Account.createFromPrivateKey(multisig1PrivateKey, networkType);
const convertMultisigAccount1Transaction = symbol_sdk_1.MultisigAccountModificationTransaction.create(symbol_sdk_1.Deadline.create(epochAdjustment), 3, 1, [
multisigAccount2.publicAccount.address,
multisigAccount3.publicAccount.address,
cosignatory4.address,
], [], networkType);
4. Announce the transactions together using an AggregateBondedTransaction.
The account #1 must lock 10
symbol.xym
to announce the transaction.
const aggregateTransaction = AggregateTransaction.createBonded(
Deadline.create(epochAdjustment),
[
convertMultisigAccount2Transaction.toAggregate(
multisigAccount2.publicAccount,
),
convertMultisigAccount3Transaction.toAggregate(
multisigAccount3.publicAccount,
),
convertMultisigAccount1Transaction.toAggregate(
multisigAccount1.publicAccount,
),
],
networkType,
[],
UInt64.fromUint(2000000),
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = multisigAccount1.sign(
aggregateTransaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with symbol.xym id
const networkCurrencyMosaicId = new MosaicId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;
const hashLockTransaction = HashLockTransaction.create(
Deadline.create(epochAdjustment),
new Mosaic(
networkCurrencyMosaicId,
UInt64.fromUint(10 * Math.pow(10, networkCurrencyDivisibility)),
),
UInt64.fromUint(480),
signedTransaction,
networkType,
UInt64.fromUint(2000000),
);
const signedHashLockTransaction = multisigAccount1.sign(
hashLockTransaction,
networkGenerationHash,
);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const listener = repositoryFactory.createListener();
const receiptHttp = repositoryFactory.createReceiptRepository();
const transactionHttp = repositoryFactory.createTransactionRepository();
const transactionService = new TransactionService(transactionHttp, receiptHttp);
listener.open().then(() => {
transactionService
.announceHashLockAggregateBonded(
signedHashLockTransaction,
signedTransaction,
listener,
)
.subscribe(
(x) => console.log(x),
(err) => console.log(err),
() => listener.close(),
);
});
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createBonded(symbol_sdk_1.Deadline.create(epochAdjustment), [
convertMultisigAccount2Transaction.toAggregate(multisigAccount2.publicAccount),
convertMultisigAccount3Transaction.toAggregate(multisigAccount3.publicAccount),
convertMultisigAccount1Transaction.toAggregate(multisigAccount1.publicAccount),
], networkType, [], symbol_sdk_1.UInt64.fromUint(2000000));
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash = '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = multisigAccount1.sign(aggregateTransaction, networkGenerationHash);
console.log(signedTransaction.hash);
// replace with symbol.xym id
const networkCurrencyMosaicId = new symbol_sdk_1.MosaicId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;
const hashLockTransaction = symbol_sdk_1.HashLockTransaction.create(symbol_sdk_1.Deadline.create(epochAdjustment), new symbol_sdk_1.Mosaic(networkCurrencyMosaicId, symbol_sdk_1.UInt64.fromUint(10 * Math.pow(10, networkCurrencyDivisibility))), symbol_sdk_1.UInt64.fromUint(480), signedTransaction, networkType, symbol_sdk_1.UInt64.fromUint(2000000));
const signedHashLockTransaction = multisigAccount1.sign(hashLockTransaction, networkGenerationHash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const listener = repositoryFactory.createListener();
const receiptHttp = repositoryFactory.createReceiptRepository();
const transactionHttp = repositoryFactory.createTransactionRepository();
const transactionService = new symbol_sdk_1.TransactionService(transactionHttp, receiptHttp);
listener.open().then(() => {
transactionService
.announceHashLockAggregateBonded(signedHashLockTransaction, signedTransaction, listener)
.subscribe((x) => console.log(x), (err) => console.log(err), () => listener.close());
});
5. The potential cosignatories must opt-in to become cosignatories. Cosign the announced AggregateTransaction with the accounts #5, #6, #7, #8, and #4.
symbol-cli transaction cosign --hash A6A374E66B32A3D5133018EFA9CD6E3169C8EEA339F7CCBE29C47D07086E068C --profile <account>