このガイドでは、パーシャルキャッシュを使用せずに、アグリゲートコンプリートトランザクションに連署名を追加する方法を説明します。
この方法は、セキュリティ上の理由で、秘密鍵をオフラインデバイス (コールドウォレット) に保管している場合に有用です。オフラインで連署名を追加することで、連署者は秘密鍵の安全を保ったまま、コールドウォレットからトランザクションを実行できます。さらに aggregate bonded transactions による、意図しない資産ロックを回避することもできます。
Alice (TDPXWF2H5G7U2NKZRJD47QR4KZPRULPAMQ4O54IK
) は 100 symbol.xym
を Bob (TCHS3AOXFGWGTN2QUUHDCXJ4SBYLIQIPNUPHHA2N
) に送信し、1 collectible モザイクを返却する、アグリゲートコンプリートトランザクションを構築していきます。
テキストエディタを開きます。そして、Alice のアカウントを使用して、アグリゲートコンプリートトランザクションを構築します。
const networkType = NetworkType.TEST_NET;
// replace with alice private key
const alicePrivatekey = '';
const aliceAccount = Account.createFromPrivateKey(alicePrivatekey, networkType);
// replace with bob public key
const bobPublicKey = '';
const bobPublicAccount = PublicAccount.createFromPublicKey(
bobPublicKey,
networkType,
);
const aliceTransferTransaction = TransferTransaction.create(
Deadline.create(epochAdjustment),
bobPublicAccount.address,
[NetworkCurrencies.PUBLIC.currency.createRelative(1000)],
PlainMessage.create('payout'),
networkType,
);
const bobTransferTransaction = TransferTransaction.create(
Deadline.create(epochAdjustment),
aliceAccount.address,
[new Mosaic(new NamespaceId('collectible'), UInt64.fromUint(1))],
PlainMessage.create('payout'),
networkType,
);
const aggregateTransaction = AggregateTransaction.createComplete(
Deadline.create(epochAdjustment),
[
aliceTransferTransaction.toAggregate(aliceAccount.publicAccount),
bobTransferTransaction.toAggregate(bobPublicAccount),
],
networkType,
[],
UInt64.fromUint(2000000),
);
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with alice private key
const alicePrivatekey = '';
const aliceAccount = symbol_sdk_1.Account.createFromPrivateKey(
alicePrivatekey,
networkType,
);
// replace with bob public key
const bobPublicKey = '';
const bobPublicAccount = symbol_sdk_1.PublicAccount.createFromPublicKey(
bobPublicKey,
networkType,
);
const aliceTransferTransaction = symbol_sdk_1.TransferTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
bobPublicAccount.address,
[symbol_sdk_1.NetworkCurrencies.PUBLIC.currency.createRelative(1000)],
symbol_sdk_1.PlainMessage.create('payout'),
networkType,
);
const bobTransferTransaction = symbol_sdk_1.TransferTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
aliceAccount.address,
[
new symbol_sdk_1.Mosaic(
new symbol_sdk_1.NamespaceId('collectible'),
symbol_sdk_1.UInt64.fromUint(1),
),
],
symbol_sdk_1.PlainMessage.create('payout'),
networkType,
);
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createComplete(
symbol_sdk_1.Deadline.create(epochAdjustment),
[
aliceTransferTransaction.toAggregate(aliceAccount.publicAccount),
bobTransferTransaction.toAggregate(bobPublicAccount),
],
networkType,
[],
symbol_sdk_1.UInt64.fromUint(2000000),
);
NetworkType networkType = repositoryFactory.getNetworkType().toFuture().get();
NetworkCurrency networkCurrency = repositoryFactory.getNetworkCurrency().toFuture()
.get();
// replace with alice private key
String alicePrivatekey = "";
Account aliceAccount = Account.createFromPrivateKey(alicePrivatekey, networkType);
// replace with bob public key
String bobPublicKey = "";
PublicAccount bobPublicAccount = PublicAccount
.createFromPublicKey(bobPublicKey, networkType);
TransferTransaction aliceTransferTransaction = TransferTransactionFactory
.create(networkType, bobPublicAccount.getAddress(),
Collections
.singletonList(networkCurrency.createRelative(BigInteger.valueOf(1000))),
PlainMessage.create("payout")).build();
TransferTransaction bobTransferTransaction = TransferTransactionFactory
.create(networkType, aliceAccount.getAddress(),
Collections.singletonList(
new Mosaic(new NamespaceId("collectible"), BigInteger.valueOf(1))),
PlainMessage.create("payout")).build();
AggregateTransaction aggregateTransaction = AggregateTransactionFactory
.createComplete(networkType, Arrays
.asList(aliceTransferTransaction.toAggregate(aliceAccount.getPublicAccount()),
bobTransferTransaction.toAggregate(bobPublicAccount)))
.maxFee(BigInteger.valueOf(2000000)).build();
Alice の秘密鍵と Bob の公開鍵が適切に設定されていることを確認してください。
Alice のキーでトランザクションに署名します。
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const generationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransactionNotComplete = aliceAccount.sign(
aggregateTransaction,
generationHash,
);
console.log(signedTransactionNotComplete.payload);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const generationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransactionNotComplete = aliceAccount.sign(
aggregateTransaction,
generationHash,
);
console.log(signedTransactionNotComplete.payload);
String generationHash = repositoryFactory.getGenerationHash().toFuture().get();
SignedTransaction signedTransactionNotComplete = aliceAccount
.sign(aggregateTransaction, generationHash);
System.out.println(signedTransactionNotComplete.getPayload());
3. Save the TypeScript file, then run it on your terminal. Copy the returned payload and send it over to Bob.
Bob は前回のステップで取得したペイロードに連署名します。
// replace with bob private key
const bobPrivateKey = '';
const bobAccount = Account.createFromPrivateKey(bobPrivateKey, networkType);
const cosignedTransactionBob = CosignatureTransaction.signTransactionPayload(
bobAccount,
signedTransactionNotComplete.payload,
generationHash,
);
console.log(cosignedTransactionBob.signature);
console.log(cosignedTransactionBob.parentHash);
// replace with bob private key
const bobPrivateKey = '';
const bobAccount = symbol_sdk_1.Account.createFromPrivateKey(
bobPrivateKey,
networkType,
);
const cosignedTransactionBob = symbol_sdk_1.CosignatureTransaction.signTransactionPayload(
bobAccount,
signedTransactionNotComplete.payload,
generationHash,
);
console.log(cosignedTransactionBob.signature);
console.log(cosignedTransactionBob.parentHash);
// replace with bob private key
String bobPrivateKey = "";
Account bobAccount = Account.createFromPrivateKey(bobPrivateKey, networkType);
CosignatureSignedTransaction cosignedTransactionBob = CosignatureTransaction
.create(aggregateTransaction)
.signWith(bobAccount);
System.out.println(cosignedTransactionBob.getSignature());
System.out.println(cosignedTransactionBob.getParentHash());
2. Bob runs the code snippet in the terminal and obtains the transaction signature and the parent hash. Finally, he shares the information back with Alice.
Bob の公開鍵、連署トランザクションハッシュ、署名を使用してトランザクションを再作成し、コンプリートとしてネットワークへアナウンスします。
const cosignatureSignedTransactions = [
new CosignatureSignedTransaction(
cosignedTransactionBob.parentHash,
cosignedTransactionBob.signature,
cosignedTransactionBob.signerPublicKey,
),
];
const rectreatedAggregateTransactionFromPayload = TransactionMapping.createFromPayload(
signedTransactionNotComplete.payload,
) as AggregateTransaction;
const signedTransactionComplete = aliceAccount.signTransactionGivenSignatures(
rectreatedAggregateTransactionFromPayload,
cosignatureSignedTransactions,
generationHash,
);
console.log(signedTransactionComplete.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransactionComplete).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
const cosignatureSignedTransactions = [
new symbol_sdk_1.CosignatureSignedTransaction(
cosignedTransactionBob.parentHash,
cosignedTransactionBob.signature,
cosignedTransactionBob.signerPublicKey,
),
];
const rectreatedAggregateTransactionFromPayload = symbol_sdk_1.TransactionMapping.createFromPayload(
signedTransactionNotComplete.payload,
);
const signedTransactionComplete = aliceAccount.signTransactionGivenSignatures(
rectreatedAggregateTransactionFromPayload,
cosignatureSignedTransactions,
generationHash,
);
console.log(signedTransactionComplete.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransactionComplete).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
BinarySerialization serialization = BinarySerializationImpl.INSTANCE;
AggregateTransactionFactory rectreatedAggregateTransactionFromPayload = (AggregateTransactionFactory) serialization
.deserializeToFactory(
ConvertUtils.getBytes(signedTransactionNotComplete.getPayload()));
//Added a new cosignature.
rectreatedAggregateTransactionFromPayload.addCosignatures(cosignedTransactionBob);
SignedTransaction signedTransactionComplete = aliceAccount
.sign(rectreatedAggregateTransactionFromPayload.build(), generationHash);
System.out.println(signedTransactionComplete.getHash());
TransactionRepository transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransactionComplete).toFuture().get();
成功すれば、Alice は 100 symbol.xym
を Bob へ送信し、1 collectible
モザイクを返却します。