2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NEM2カタパルトで双方向ペイメントチャネルするには その3 ペイロードの送信と罰則

Last updated at Posted at 2019-01-07

はじめに

前回の記事

前回は、トランザクションを作ることにのみ専念した。

トランザクションを作り、送信し、連署し、承認を確認した。

しかし、まだ検証していないものが2つある。

署名済みトランザクションを相手に渡す

ペイメントチャネルでは、署名済みトランザクションを送信せずに相手に渡す必要がある。

そこで今回は、シリアライズされたトランザクションを送信し、連署し、承認されることを確認する。

裏切りの代償

前回の記事では、ペイメントチャネルによる取引がスムーズにいった場合のみを対象とした。

そこで今回は、裏切りのケースを想定し、古いコミットメントトランザクションを送信し、もう一方が罰を発動できるかを確認する。

作ってみる

ペイロードを送信するサンプル。その後、連署しているのだが、これは通常の流れ。

function sendAndCosignAggregateTransaction(payloads, address1, account2, addressG) {
    return new Promise((resolve, reject) => {
        const calcurateTransactionHash = function(payload) {
            const hashInputPayload =
                payload.substr(4*2,32*2) +
                payload.substr((4+64)*2,32*2) +
                payload.substr((4+64+32)*2);
            const hasher = sha3_256.create();
            return hasher.update(Buffer.from(hashInputPayload, 'hex')).hex().toUpperCase();
        }
        const cosignAggregateBondedTransaction = function(transaction, account) {
            const cosignatureTransaction = CosignatureTransaction.create(transaction);
            const signedTransaction = account.signCosignatureTransaction(cosignatureTransaction);
            return signedTransaction;
        }
        const payload = payloads[0];
        const hash = calcurateTransactionHash(payload);
        const lockFundsTxPayload = payloads[1];
        const lockFundsTxHash = calcurateTransactionHash(lockFundsTxPayload);
        const listener = new Listener(ENDPOINT);
        const transactionHttp = new TransactionHttp(ENDPOINT);
        listener.open().then(() => {
            return new Promise((resolveReq, rejectReq) => {
                console.log(lockFundsTxHash);
                request({
                    url: `${ENDPOINT}/transaction`,
                    method: 'PUT',
                    headers: {
                        'Content-Type':'application/json'
                    },
                    json: {"payload": lockFundsTxPayload}
                }, (error, response, body) => {
                    console.log(body);
                    error ? rejectReq(error) : resolveReq();
                });
            });
        }).then(() => {
            listener.confirmed(addressG).pipe(
                filter((transaction) => transaction.transactionInfo !== undefined
                && transaction.transactionInfo.hash === lockFundsTxHash),
                flatMap(ignored => rx.from(new Promise((resolveReq, rejectReq) => {
                    console.log(hash);
                    request({
                        url: `${ENDPOINT}/transaction/partial`,
                        method: 'PUT',
                        headers: {
                            'Content-Type':'application/json'
                        },
                        json: {payload}
                    }, (error, response, body) => {
                        error ? rejectReq(error) : resolveReq(body);
                    });
                })))
            ).subscribe(
                x => console.log(x),
                err => console.error(err)
            );
            listener.aggregateBondedAdded(account2.address).pipe(
                filter((_) => !_.signedByAccount(account2.publicAccount)),
                map(transaction => cosignAggregateBondedTransaction(transaction, account2)),
                flatMap(cosignatureSignedTransaction => transactionHttp.announceAggregateBondedCosignature(cosignatureSignedTransaction))
            ).subscribe(
                x => console.log(x),
                err => console.error(err)
            );
            listener.confirmed(address1).pipe(
                filter((transaction) => transaction.transactionInfo !== undefined
                && transaction.transactionInfo.hash === hash)
            ).subscribe(
                ignore => {
                    listener.close();
                    resolve();
                },
                err => console.error(err)
            );
        }).catch((error) => {
            console.error(error);
        });
    });
}

裏切りのパターンは、普通のSecret Proofなので割愛する。

送ってみる

ソースはこちら

順番に以下の処理を行う。

  • マルチシグ、Alice、Bobの秘密鍵を生成する
  • AliceとBobにXEMを送る
  • マルチシグ用アカウントをマルチシグ化する
  • 残高を表示する
  • Opening Transactionのペイロードを作成する
  • Commitment Transaction 1のペイロードを作成する
  • Opening Transactionを送信する
  • 残高を表示する
  • Commitment Transaction 2のペイロードを作成する
  • BobがCommitment Transaction 1を送信する
  • 残高を表示する
  • Aliceが裏切りの代償を発動する
  • 残高を表示する
$ node paymentch9c.js 
=== send XEM first ===
EB4B38E0166CC7F14E0148B0B1CA9FEC0D83EBC89B2D8DB009A6465AE84F46D3
connection open
TransactionAnnounceResponse {
  message: 'packet 9 was pushed to the network via /transaction' }
=== create multisig account ===
C97C074389684061FD9A5876CB01E5343F5E84FBF17DB7B9B3F0660D5229E520
connection open
TransactionAnnounceResponse {
  message: 'packet 9 was pushed to the network via /transaction' }
=== show balance [Multisig, Alice, Bob] ===
[ 0, 5000000, 5000000 ]
=== create opning transaction payload ===
=== create commitment 1 transaction payload ===
=== send opening transaction ===
connection open
9254669288957604223ED99703D8A7759CAD4E73E1C54FBF2CBDDC481E7C186F
{ message: 'packet 9 was pushed to the network via /transaction' }
B0CAA690C5B19F371CDDB1FEF1E9E3DC3BB03C7E3018AB1AF0755857D333EC6A
{ message:
   'packet 500 was pushed to the network via /transaction/partial' }
TransactionAnnounceResponse {
  message:
   'packet 501 was pushed to the network via /transaction/cosignature' }
=== show balance [Multisig, Alice, Bob] ===
[ 10000000, 0, 0 ]
=== create commitment 2 transaction payload ===
=== cheat (send old commitment transaction) ===
connection open
9D3CC19B769B5F0282F297CDE0545757929E4D75B1F28BAAE964F171FE7B8524
{ message: 'packet 9 was pushed to the network via /transaction' }
E1880F5B30D430F3A28B18CDCB88623783A2BBCD22AA3CF30BBC32208C18914A
{ message:
   'packet 500 was pushed to the network via /transaction/partial' }
TransactionAnnounceResponse {
  message:
   'packet 501 was pushed to the network via /transaction/cosignature' }
=== show balance [Multisig, Alice, Bob] ===
[ 0, 4000000, 0 ]
=== penalty (collect all XEM) ===
D9DEDBB21B4883EB37F7688AC940EAC5FD4E201F0824E857E50AB4D5F07D5484
connection open
TransactionAnnounceResponse {
  message: 'packet 9 was pushed to the network via /transaction' }
=== show balance [Multisig, Alice, Bob] ===
[ 0, 10000000, 0 ]

Opening Transaction

Commitment Transaction 1 (Cheat)

Secret Proof Transaction (Penalty)

まとめ

作ることができる

関連

NEM2カタパルトで双方向ペイメントチャネルするには その1 概要
https://qiita.com/planethouki/items/c22a21836d913418de82

NEM2カタパルトで双方向ペイメントチャネルするには その2 トランザクションは作れるのか
https://qiita.com/planethouki/items/53415a14b34bebd450fc

NEM2カタパルトで双方向ペイメントチャネルするには その3 ペイロードの送信と罰則
https://qiita.com/planethouki/items/945239fe04d2af1fb203

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?