Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

nem catapult deadlineとmaxTransactionLifetime

More than 1 year has passed since last update.

概要

catapult-serverの設定にmaxTransactionLifetime=24hというのがある。config-network.propertiesに記載されており、トランザクションの有効期限に関するものだと思う。

NEMのトランザクションには、Deadlineという項目があり、ミリ秒単位で時刻を指定する。この時刻を過ぎると、承認されていないトランザクションは破棄される。かといって、長く設定することはできず、24時間以内という制限がある。

Aggregate Bonded Txや、Lock Funds Tx、Secret Lock Txなど、承認まで時間がかかるものは、これに気を配る必要がある。(なのでオフチェーン決済なんかは辛そう)

例えば、こちらの例1のような、マルチシグを使って工業製品の品質証明モザイクを送付するような事例では、24時間では足りないと思う。

なので今回は、設定を変更してみて、確かに24時間以上のDeadlineが有効なのかどうかをやってみようと思う。

やってみる

今回は、3つのパターンを設定したチェーンを用意した。

  1. 初期設定の状態(24時間)
  2. maxTransactionLifetime=720hに設定(30日)
  3. maxTransactionLifetime=8766000hに設定(1000年)

それぞれに、以下のDeadlineを設定したトランスファートランザクションをアナウンスしてみる。

  1. 9.5日後(10進数で820800000、16進数で30EC6A00)
  2. 35日後(10進数で72024588288、16進数で0x10C5000000)

それで、以下のようになると想定。

チェーン/Deadline 9.5日後 35日後
24時間 × -
30日 ×
1000年

※ペイロード上でのDeadlineは、リトルエンディアン表現であることに注意。

初期設定の状態(24時間)のチェーン

9.5日後に設定したトランザクションを作る。Deadline415628FD10000000

$ node transfer95.js
payload: A5000000DC9ED42254FD59AB7B4724212E56B2AC6C7250E8D067C77CBA02F3D4D789513132922CEFA1605E4275DA92F3421E08D1DBA65D1350641F02B913ABD336D0A60768599F9BD72D20640DFE45450B68777C8FDEE4B56BDB1A997FB8BD292AE843F2039054410000000000000000415628FD1000000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010029CF5FD941AD25D58096980000000000
hash: 5EDC333A6AEB3D9FFDAC795CC5EA55AB0D996B2671B873F69F267C2FF19D5377

アナウンスする。

$ curl -X PUT -H 'Content-Type:application/json' -d '{"payload": "A5000000DC9ED42254FD59AB7B4724212E56B2AC6C7250E8D067C77CBA02F3D4D789513132922CEFA1605E4275DA92F3421E08D1DBA65D1350641F02B913ABD336D0A60768599F9BD72D20640DFE45450B68777C8FDEE4B56BDB1A997FB8BD292AE843F2039054410000000000000000415628FD1000000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010029CF5FD941AD25D58096980000000000"}' http://localhost:3000/transaction
{"message":"packet 9 was pushed to the network via /transaction"}

トランザクションは失敗。理由はFailure_Core_Future_Deadline

$ curl http://localhost:3000/transaction/5EDC333A6AEB3D9FFDAC795CC5EA55AB0D996B2671B873F69F267C2FF19D5377/status
{
  "hash": "5EDC333A6AEB3D9FFDAC795CC5EA55AB0D996B2671B873F69F267C2FF19D5377",
  "status": "Failure_Core_Future_Deadline",
  "deadline": [
    4247279169,
    16
  ],
  "group": "failed"
}

最新のブロック高のタイムスタンプを見てみる

"timestamp": [
  3418467958,
  16
],

その差は828811211[ms]で、およそ230時間。だいたい9.5日。想定通りである。

720hに設定(30日)のチェーン

9.5日後に設定したトランザクション

先ほどと全く同じトランザクションをアナウンス。Deadline415628FD10000000

$ curl -X PUT -H 'Content-Type:application/json' -d '{"payload": "A5000000DC9ED42254FD59AB7B4724212E56B2AC6C7250E8D067C77CBA02F3D4D789513132922CEFA1605E4275DA92F3421E08D1DBA65D1350641F02B913ABD336D0A60768599F9BD72D20640DFE45450B68777C8FDEE4B56BDB1A997FB8BD292AE843F2039054410000000000000000415628FD1000000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010029CF5FD941AD25D58096980000000000"}' http://localhost:3000/transaction
{"message":"packet 9 was pushed to the network via /transaction"}

成功した。承認済みにもなった。

$ curl http://localhost:3000/transaction/5EDC333A6AEB3D9FFDAC795CC5EA55AB0D996B2671B873F69F267C2FF19D5377/status
{
  "group": "confirmed",
  "status": "Success",
  "hash": "5EDC333A6AEB3D9FFDAC795CC5EA55AB0D996B2671B873F69F267C2FF19D5377",
  "deadline": [
    4247279169,
    16
  ],
  "height": [
    3,
    0
  ]
}

35日後に設定したトランザクション

トランザクションを作る。DeadlineAAFC0B8011000000

$ node transfer35.js
payload: A500000034E9A57840113BA3361E45818B9E657B6B72302F4D98B7F9AB7FE4199D619AB0AD04F46A11A5251AD2F40841FA2AA69B62C17D91925B9C931F142C1EF538AA0768599F9BD72D20640DFE45450B68777C8FDEE4B56BDB1A997FB8BD292AE843F2039054410000000000000000AAFC0B801100000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010029CF5FD941AD25D58096980000000000
hash: D9FF5624BF3D741A60D6908516E740020EF1B0949EE747805CB805FF42AA3459

アナウンスする。

$ curl -X PUT -H 'Content-Type:application/json' -d '{"payload": "A500000034E9A57840113BA3361E45818B9E657B6B72302F4D98B7F9AB7FE4199D619AB0AD04F46A11A5251AD2F40841FA2AA69B62C17D91925B9C931F142C1EF538AA0768599F9BD72D20640DFE45450B68777C8FDEE4B56BDB1A997FB8BD292AE843F2039054410000000000000000AAFC0B801100000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010029CF5FD941AD25D58096980000000000"}' http://localhost:3000/transaction
{"message":"packet 9 was pushed to the network via /transaction"}

トランザクションは失敗。理由はFailure_Core_Future_Deadline。

$ curl http://localhost:3000/transaction/D9FF5624BF3D741A60D6908516E740020EF1B0949EE747805CB805FF42AA3459/status
{"hash":"D9FF5624BF3D741A60D6908516E740020EF1B0949EE747805CB805FF42AA3459","status":"Failure_Core_Future_Deadline","deadline":[2148269226,17],"group":"failed"}

最新のブロック高のタイムスタンプを見てみる。

"timestamp": [
  3418467958,
  16
],

これを16進数に直すと、BigEndianで0x10CBC1AE76。10進数で72137944694

トランザクションのDeadlineとの差分は、10進数で3024768564。だいたい35日。

8766000hに設定(1000年)のチェーン

9.5日後に設定したトランザクション

先ほどと全く同じトランザクションをアナウンス。Deadlineは415628FD10000000。

$ curl -X PUT -H 'Content-Type:application/json' -d '{"payload": "A5000000DC9ED42254FD59AB7B4724212E56B2AC6C7250E8D067C77CBA02F3D4D789513132922CEFA1605E4275DA92F3421E08D1DBA65D1350641F02B913ABD336D0A60768599F9BD72D20640DFE45450B68777C8FDEE4B56BDB1A997FB8BD292AE843F2039054410000000000000000415628FD1000000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010029CF5FD941AD25D58096980000000000"}' http://localhost:3000/transaction
{"message":"packet 9 was pushed to the network via /transaction"}

成功した。

$ curl http://localhost:3000/transaction/5EDC333A6AEB3D9FFDAC795CC5EA55AB0D996B2671B873F69F267C2FF19D5377/status
{
  "group": "confirmed",
  "status": "Success",
  "hash": "5EDC333A6AEB3D9FFDAC795CC5EA55AB0D996B2671B873F69F267C2FF19D5377",
  "deadline": [
    4247279169,
    16
  ],
  "height": [
    4,
    0
  ]
}

35日後に設定したトランザクション

先ほどと全く同じトランザクションをアナウンス。DeadlineはAAFC0B8011000000。

$ curl -X PUT -H 'Content-Type:application/json' -d '{"payload": "A500000034E9A57840113BA3361E45818B9E657B6B72302F4D98B7F9AB7FE4199D619AB0AD04F46A11A5251AD2F40841FA2AA69B62C17D91925B9C931F142C1EF538AA0768599F9BD72D20640DFE45450B68777C8FDEE4B56BDB1A997FB8BD292AE843F2039054410000000000000000AAFC0B801100000090758EB47C28D6143BAA3DE6A8D9C319B503A1BFD8E789E9E20100010029CF5FD941AD25D58096980000000000"}' http://localhost:3000/transaction
{"message":"packet 9 was pushed to the network via /transaction"}

こちらも成功した。

$ curl http://localhost:3000/transaction/D9FF5624BF3D741A60D6908516E740020EF1B0949EE747805CB805FF42AA3459/status
{
  "group": "confirmed",
  "status": "Success",
  "hash": "D9FF5624BF3D741A60D6908516E740020EF1B0949EE747805CB805FF42AA3459",
  "deadline": [
    2148269226,
    17
  ],
  "height": [
    6,
    0
  ]
}

code

nem2-sdkでトランザクションを作る際は、チェック機能が働くため24時間以上のDeadlineが設定できないようになっている。

そこで、Deadlineを手動で計算し、ペイロードを修正し、再度署名して、再度トランザクションハッシュ導出をしている。

ちなみに、nem2-sdkでのDeadlineのデフォルト値は、2時間となっているようです。

const nem2lib = require("nem2-library");
const nem2Sdk = require("nem2-sdk");
const crypto = require("crypto");
const jssha3 = require('js-sha3');

const Address = nem2Sdk.Address,
    Deadline = nem2Sdk.Deadline,
    Account = nem2Sdk.Account,
    UInt64 = nem2Sdk.UInt64,
    NetworkType = nem2Sdk.NetworkType,
    PlainMessage = nem2Sdk.PlainMessage,
    TransferTransaction = nem2Sdk.TransferTransaction,
    Mosaic = nem2Sdk.Mosaic,
    MosaicId = nem2Sdk.MosaicId,
    TransactionHttp = nem2Sdk.TransactionHttp;

const sha3_512 = jssha3.sha3_512;
const sha3_256 = jssha3.sha3_256;


const recipientAddress = 'SB2Y5ND4FDLBIO5KHXTKRWODDG2QHIN73DTYT2PC';

const transferTransaction = TransferTransaction.create(
    Deadline.create(),
    Address.createFromRawAddress(recipientAddress),
    [new Mosaic(new MosaicId('nem:xem'), UInt64.fromUint(10000000)),],
    PlainMessage.create(''),
    NetworkType.MIJIN_TEST,
);


const privateKey = '72C95EBB2C20AAA47614BB12AFD7878015016AF27BD12CC5F50DF963583F8B5E';

const account = Account.createFromPrivateKey(privateKey,NetworkType.MIJIN_TEST);

const signedTransaction = account.sign(transferTransaction);

// const signData = signedTransaction.payload.substring((4+64+32)*2,(4+64+32+12)*2)
//     .concat('415628FD', '10000000',
//         signedTransaction.payload.substring((4+64+32+12+8)*2));
const signData = signedTransaction.payload.substring((4+64+32)*2,(4+64+32+12)*2)
    .concat('AAFC0B80', '11000000',
        signedTransaction.payload.substring((4+64+32+12+8)*2));
const keypair = nem2lib.KeyPair.createKeyPairFromPrivateKeyString(privateKey);
const signature = nem2lib.KeyPair.sign(keypair, signData);
const newPayload = signedTransaction.payload.substring(0,4*2)
    .concat(nem2lib.convert.uint8ToHex(signature),
        signedTransaction.payload.substring((4+64)*2,(4+64+32)*2),
        signData);



const toHashed = newPayload.substring(4*2,(4+32)*2)
    .concat(newPayload.substring((4+64)*2));
const hasher = sha3_256.create();
const hash = hasher.update(Buffer.from(toHashed, 'hex')).hex().toUpperCase();


// const transactionHttp = new TransactionHttp('http://localhost: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);

console.log('payload: ' + newPayload);
console.log('hash: ' + hash);

//curl -X PUT -H 'Content-Type:application/json' -d '{"payload": ""}' http://localhost:3000/transaction

所感

Deadlineが変更できることがわかった。これで、例えば署名が揃うまで時間がかかるモデルにも適用できると思う。

ただし、厳密には数日間トランザクションが未承認のままで存在していることを確認する必要がある。

Deadlineを長くとると、未承認トランザクションがたまっていくので、長くしすぎにも注意。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away