はじめに
トランザクションの手数料は、トランザクションのデータサイズに比例します。例えば、比例定数が100で、トランザクションのサイズが165バイトだった場合、手数料は16500になります。分割数が6なので、0.0165XEM?になるでしょう。
なので、アグリゲートトランザクションを使用して、できるだけサイズが小さくなるようにすることで、手数料が削減できる可能性があります。
トランスファートランザクションを複数回送信する VS アグリゲートトランザクシでまとめる
トランザクションのサイズ比較をします。
A:モザイク1種類でメッセージなしのペイロードのトランスファートランザクション
const {
Account,
Address,
Deadline,
NetworkCurrencyMosaic,
NetworkType,
PlainMessage,
TransactionHttp,
TransferTransaction,
UInt64
} = require("nem2-sdk");
const recipientAddress = 'SB2Y5ND4FDLBIO5KHXTKRWODDG2QHIN73DTYT2PC';
const generationHash = 'AC8EE4E2D1FEA3C84D5E8DC8D032B16FC86EB89B494B1D4A0A5E7CD66BC4AC30';
const privateKey = '7808B5B53ECF24E40BE17B8EC3D0EB5F7C3F3D938E0D95A415F855AD4C27B2A4';
const transferTransaction = TransferTransaction.create(
Deadline.create(),
Address.createFromRawAddress(recipientAddress),
[NetworkCurrencyMosaic.createRelative(0)],
PlainMessage.create(''),
NetworkType.MIJIN_TEST,
UInt64.fromUint(0)
);
const account = Account.createFromPrivateKey(privateKey,NetworkType.MIJIN_TEST);
const signedTransaction = account.sign(transferTransaction, generationHash);
// const transactionHttp = new TransactionHttp('http://13.114.200.132:3000');
// transactionHttp.announce(signedTransaction).subscribe(
// x => console.log(x),
// err => console.error(err)
// );
console.log('HASH: ' + signedTransaction.hash);
console.log('SIGNER: ' + signedTransaction.signer);
console.log('PAYLOAD: ' + signedTransaction.payload);
HASH: 9D9C55277DEF5BB05B83150990F3D4CDE63BBD2375D822EAFA24E028D4F9C6CA
SIGNER: 5D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C
PAYLOAD: A50000008B1139BE7695D6BE6A011E6F7B12AF0C9120191257FA09C7C139AF7815A011A739D3139C941C1358FA42A4B177485FCE35EDB7E7998A5E5BBB34F32480F854095D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C0390544100000000000000002F1B00761700000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010044B262C46CEABB850000000000000000
B:モザイク1種類でメッセージなしのトランスファートランザクションを10個インナートランザクションにしたアグリゲートトランザクション
const {
Account,
AggregateTransaction,
Deadline,
NetworkCurrencyMosaic,
NetworkType,
PlainMessage,
TransactionHttp,
TransferTransaction,
UInt64
} = require("nem2-sdk");
const numAddrs = 10;
const recipientAddresses = (() => {
const addrs = [];
for (let i = 0; i < numAddrs; i++) {
const newAddr = Account.generateNewAccount(NetworkType.MIJIN_TEST).address;
addrs.push(newAddr);
}
return addrs;
})();
const generationHash = 'AC8EE4E2D1FEA3C84D5E8DC8D032B16FC86EB89B494B1D4A0A5E7CD66BC4AC30';
const privateKey = '7808B5B53ECF24E40BE17B8EC3D0EB5F7C3F3D938E0D95A415F855AD4C27B2A4';
const transferTransactions = (() => {
const txs = [];
for (let i = 0; i < numAddrs; i++) {
const transferTransaction = TransferTransaction.create(
Deadline.create(),
recipientAddresses[i],
[NetworkCurrencyMosaic.createRelative(0)],
PlainMessage.create(''),
NetworkType.MIJIN_TEST,
UInt64.fromUint(0)
);
txs.push(transferTransaction);
}
return txs;
})();
const account = Account.createFromPrivateKey(privateKey,NetworkType.MIJIN_TEST);
const aggregateTransaction = AggregateTransaction.createComplete(
Deadline.create(),
transferTransactions.map(tx => tx.toAggregate(account.publicAccount)),
NetworkType.MIJIN_TEST,
[],
UInt64.fromUint(0)
);
const signedTransaction = account.sign(aggregateTransaction, generationHash);
// const transactionHttp = new TransactionHttp('http://13.114.200.132:3000');
// transactionHttp.announce(signedTransaction).subscribe(
// x => console.log(x),
// err => console.error(err)
// );
console.log('HASH: ' + signedTransaction.hash);
console.log('SIGNER: ' + signedTransaction.signer);
console.log('PAYLOAD: ' + signedTransaction.payload);
HASH: 0B16ADEFAD2DAE111AF03AF8830DD21EFA24D9BAF72290B9F43517A3AB843D90
SIGNER: 5D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C
PAYLOAD: CE030000F17FD8F4B03E1FB0254156C9A088EC0D9A469388DCF9E73792FAF05409E31C3088E0F0E690E58FB9664AA926B0517DC7272551F54FD2A7B91E03A992B71B52085D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C029041410000000000000000F7C2FC751700000052030000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C03905441903317B57BB746AAF094117C797F52C54822BDE503F50921880100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C03905441908E6211E7F43024B55040BD526C9E23B6F2E7598FE17962860100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C0390544190FB5F83DA722003C36E3DA64429F4495A34D9E2E1155B6FB40100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C039054419062EE63C3BBF3B4735228B89D6932D00D8C8974C7EC48642C0100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C0390544190070FE771317883905A24C6E942F3B8CF125BD9F916F81F2F0100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C039054419050330873A3C9FF230229E0B3E0B812A3C15DE9F005BD9A320100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C03905441902E55B16A88B683E3898983E2D1F8C270D486107B090943280100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C0390544190B3ACD865B59B27834DBCBBF9F9D788386EE285EA1414414A0100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C0390544190B898F302BF3ECDB3C70A7A9884A103EAA9B10E5E474BA7F10100010044B262C46CEABB850000000000000000550000005D9513282B65A12A1B68DCB67DB64245721F7AE7822BE441FE813173803C512C0390544190CEB187052546C0296C11D138B4609BE6AD0BF0C1BB3E8C4A0100010044B262C46CEABB850000000000000000
結果的なもの
Aは165バイト、Bは974バイトです。
Aを10回送ると、Bと同じことをしたことになります(場合によります)。
Aの10回は、1650バイトなので、974バイトに対して、およそ40%の削減が可能かと思われます。
n
10回に限定しない場合。
トランスファー数をn
とすると、
A: 165 * n
B: 124 + 85 * n
グラフにすると
このような感じになります。
おわりに
10個程度を集約すると、40%の手数料削減になることがわかりました。
集約することによって、単純に手数料の削減だけではなく、アプリケーションとAPI間の通信回数の削減にもつながると思いますし、ブロック承認を待つ回数も減らせると思います。
逆に、どれか1つでも失敗すると、全部なかったことになります。例えば残高が足りなかったなど。これはメリットでもありデメリットでもあります。
やりたいことに対して、どの方法が適しているのかをしっかりと検討する必要があると思います。