本記事は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))