10
12

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 1 year has passed since last update.

Symbolブロックチェーンで一人が複数人に送金するトランザクションをPythonで作成する

Last updated at Posted at 2021-05-03

本記事はPythonでSymbolブロックチェーン連載の2回目です。

PythonでSymbolブロックチェーンの送金プログラムを書いてみる。
Symbolブロックチェーンで一人が複数人に送金するトランザクションをPythonで作成する
Symbolブロックチェーンで複数人が同時に送金するトランザクションをPythonで作成する
Symbolブロックチェーンで複数人が同時に送金するトランザクションをPythonで作成する(2)

今回からPythonでアグリートトランザクションを実行してみます。
前回のこの記事を先にお読みください。

今回は一人が複数人に送金する場合を想定します。

追記)みーちさんがnemlogにmainnetでの送金記事をアップしていただいてます。

インポート
from binascii import unhexlify
from symbolchain.core.CryptoTypes import PrivateKey
from symbolchain.core.symbol.KeyPair import KeyPair
from symbolchain.core.facade.SymFacade import SymFacade

facade = SymFacade('public_test')

送金者の生成
b = unhexlify("896E43895B908AF5847ECCB2645543751D94BD87E71058B003417FED5123****")

alicePrikey = PrivateKey(b)
aliceKeypair = KeyPair(alicePrikey)
alicePubkey = aliceKeypair.public_key
aliceAddress = facade.network.public_key_to_address(alicePubkey)
str(aliceAddress)

送信者としてAliceアカウントを秘密鍵から生成します。

受信者の生成
bobPrikey = PrivateKey.random()
bobKeypair = SymFacade.KeyPair(bobPrikey)
bobPubkey = bobKeypair.public_key
bobAddress = facade.network.public_key_to_address(bobPubkey)

carolPrikey = PrivateKey.random()
carolKeypair = SymFacade.KeyPair(carolPrikey)
carolPubkey = carolKeypair.public_key
carolAddress = facade.network.public_key_to_address(carolPubkey)

受信者としてBob,Carolアカウントを新規に作成します。

トランザクション作成
msg = 'test'
bobTx = facade.transaction_factory.create_embedded({
    'type': 'transfer',
    'signer_public_key': alicePubkey,
    'recipient_address': bobAddress,
    'message': bytes(1) + msg.encode('utf8')
})

carolTx = facade.transaction_factory.create_embedded({
    'type': 'transfer',
    'signer_public_key': alicePubkey,
    'recipient_address': carolAddress,
    'message': bytes(1) + msg.encode('utf8')
})

2種類のトランザクションを作成します。受信者はそれぞれBob,Carolですが、送信者はAlice一人です。

マークルハッシュの作成
from symbolchain.core.symbol.MerkleHashBuilder import MerkleHashBuilder
from symbolchain.core.CryptoTypes import Hash256
import sha3

hash_builder = MerkleHashBuilder()
hash_builder.update(Hash256(sha3.sha3_256(bobTx.serialize()).digest()))
hash_builder.update(Hash256(sha3.sha3_256(carolTx.serialize()).digest()))
merkle_hash = hash_builder.final()

複数のトランザクションで構成されるため、それぞれのトランザクションハッシュからアグリゲートトランザクションのハッシュを導出しておきます。

アグリゲートトランザクションの作成

import datetime
deadline = (int((datetime.datetime.today() + datetime.timedelta(hours=2)).timestamp()) - 1637848847) * 1000

aggregate = facade.transaction_factory.create({
    'type': 'aggregateComplete',
    'signer_public_key': alicePubkey,
    'fee': 1000000,
    'deadline': deadline,
    'transactions_hash': merkle_hash,
    'transactions': [bobTx,carolTx]
})

signature = facade.sign_transaction(aliceKeypair, aggregate)
aggregate.signature = signature.bytes

先ほど作成したトランザクションを配列に詰めてアグリゲートトランザクションを作成して署名します。

ネットワークへアナウンス
from binascii import hexlify
payload = {"payload": hexlify(aggregate.serialize()).decode('utf8').upper()}

import json
json = json.dumps(payload)

headers = {'Content-type': 'application/json'}
import http.client

conn = http.client.HTTPConnection("sym-test-01.opening-line.jp",3000)
conn.request("PUT", "/transactions", json,headers)

response = conn.getresponse()
print(response.status, response.reason)

署名したトランザクションをJSON化してネットワークに通知します。

確認
hash = facade.hash_transaction(aggregate)
print('https://sym-test-01.opening-line.jp:3001/transactionStatus/' + str(hash))
全ソースコード
from binascii import unhexlify
from symbolchain.core.CryptoTypes import PrivateKey
from symbolchain.core.symbol.KeyPair import KeyPair
from symbolchain.core.facade.SymFacade import SymFacade

facade = SymFacade('public_test')

b = unhexlify("896E43895B908AF5847ECCB2645543751D94BD87E71058B003417FED5123****")

alicePrikey = PrivateKey(b)
aliceKeypair = KeyPair(alicePrikey)
alicePubkey = aliceKeypair.public_key
aliceAddress = facade.network.public_key_to_address(alicePubkey)
str(aliceAddress)


bobPrikey = PrivateKey.random()
bobKeypair = SymFacade.KeyPair(bobPrikey)
bobPubkey = bobKeypair.public_key
bobAddress = facade.network.public_key_to_address(bobPubkey)

carolPrikey = PrivateKey.random()
carolKeypair = SymFacade.KeyPair(carolPrikey)
carolPubkey = carolKeypair.public_key
carolAddress = facade.network.public_key_to_address(carolPubkey)


msg = 'test'
bobTx = facade.transaction_factory.create_embedded({
    'type': 'transfer',
    'signer_public_key': alicePubkey,
    'recipient_address': bobAddress,
    'message': bytes(1) + msg.encode('utf8')
})

carolTx = facade.transaction_factory.create_embedded({
    'type': 'transfer',
    'signer_public_key': alicePubkey,
    'recipient_address': carolAddress,
    'message': bytes(1) + msg.encode('utf8')
})

from symbolchain.core.symbo.MerkleHashBuilder import MerkleHashBuilder
from symbolchain.core.CryptoTypes import Hash256
import sha3

hash_builder = MerkleHashBuilder()
hash_builder.update(Hash256(sha3.sha3_256(bobTx.serialize()).digest()))
hash_builder.update(Hash256(sha3.sha3_256(carolTx.serialize()).digest()))
merkle_hash = hash_builder.final()

import datetime
deadline = (int((datetime.datetime.today() + datetime.timedelta(hours=2)).timestamp()) - 1637848847) * 1000

aggregate = facade.transaction_factory.create({
    'type': 'aggregateComplete',
    'signer_public_key': alicePubkey,
    'fee': 1000000,
    'deadline': deadline,
    'transactions_hash': merkle_hash,
    'transactions': [bobTx,carolTx]
})

signature = facade.sign_transaction(aliceKeypair, aggregate)
aggregate.signature = signature.bytes


from binascii import hexlify
payload = {"payload": hexlify(aggregate.serialize()).decode('utf8').upper()}

import json
jsonPayload = json.dumps(payload)

headers = {'Content-type': 'application/json'}
import http.client

conn = http.client.HTTPConnection("sym-test-01.opening-line.jp",3000)
conn.request("PUT", "/transactions", jsonPayload ,headers)

response = conn.getresponse()
print(response.status, response.reason)

hash = facade.hash_transaction(aggregate)
print('http://sym-test-01.opening-line.jp:3000/transactionStatus/' + str(hash))


10
12
1

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
10
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?