OSDN Git Service

fix bug
[bytom/pybtm.git] / pybtm / transaction.py
index 6a62792..f9e89ee 100644 (file)
@@ -5,24 +5,22 @@ from .receiver import *
 
 # submit_transaction broadcast raw transaction
 # raw_transaction_str is signed transaction,
-# network_str is mainnet or testnet
 # test data 1:
-#   raw_transaction_str: 070100010160015e0873eddd68c4ba07c9410984799928288ae771bdccc6d974e72c95727813461fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8094ebdc030101160014052620b86a6d5e07311d5019dffa3864ccc8a6bd630240312a052f36efb9826aa1021ec91bc6f125dd07f9c4bff87014612069527e15246518806b654d57fff8b6fe91866a19d5a2fb63a5894335fce92a7b4a7fcd340720e87ca3acdebdcad9a1d0f2caecf8ce0dbfc73d060807a210c6f225488347961402013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8082eee0020116001418028ef4f8b8c278907864a1977a5ee6707b2a6b00013cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b8b872011600142935e4869d0317d9701c80a02ecf888143cb9dd200
-#   network_str: testnet
-def submit_transaction(raw_transaction_str, network_str):
+#   raw_transaction_hexstr: 070100010160015e5dfc352f9247985e92b2688a9a0a0e3e45a52f633c7d2c35cf6485fc1f03a89cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8094ebdc030101160014052620b86a6d5e07311d5019dffa3864ccc8a6bd630240988348a301c86563eb16105cc0c7e12e8cd1fbc7e9031933dac05a32d2a696bc77b83f25a99a4a9458d976c5327b8004918545a3fde567f28d805f741db54e0b20e87ca3acdebdcad9a1d0f2caecf8ce0dbfc73d060807a210c6f225488347961402013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b6f7f302011600147950bb5fcfb1c3fe14198c14ebd4ad85bb69bbc500013cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8084af5f011600141d8e1c2d71843f41e2131d7fd6df8b47e2cf56b900
+#   submit_url: https://blockmeta.com/api/wisdom/broadcast-transaction
+# test data 2:
+#   raw_transaction_hexstr: 07010001015f015d2f4a8f10afbc0448779fadd916a3f1b8518ffe0b7d20fdf470d8e9b4993ef2b4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0d8883200011600144a594e3e4cbbd87629476e7ee24c1637df66c0b76302406fd39079681118840fd6fd66cdff769f2d05d8520312e9dd559dc23c36a3cb3921e47cba233d5d2267eb0f128a908d1bab877e172e880d3f36dc6a5e5826540c202854e5c181f5a862edd190e413d75937549758ef4902e1475aac52623f0a239302013cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc09dd81001160014f63f68597df5c88a92e04229e0fd08a3584ade3b00013cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80e1eb1701160014664f28ec6ab8826a028658dc0d0d1f94c6e20fa300
+#   submit_url: https://blockmeta.com/api/v2/broadcast-transaction
+def submit_transaction(raw_transaction_hexstr, submit_url):
     raw_transaction_dict = {
-        "transaction": raw_transaction_str
+        "transaction": raw_transaction_hexstr
     }
     raw_transaction_json = json.dumps(raw_transaction_dict)
     headers = {
         "content-type": "application/json",
         "accept": "application/json"
     }
-    if network_str == "mainnet":
-        url = "https://blockmeta.com/api/v2/broadcast-transaction"
-    else:
-        url = "https://blockmeta.com/api/wisdom/broadcast-transaction"
-    response = requests.post(url, headers=headers, data=raw_transaction_json)
+    response = requests.post(submit_url, headers=headers, data=raw_transaction_json)
     return response.text[:-1]
 
 
@@ -124,7 +122,7 @@ def get_coinbase_input_id(prepare_coinbase_input_id_hexstr):
 '''
 decode_raw_tx decode raw transaction
 testdata 1:
-    raw_tx_str: 070100010161015f28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8099c4d5990100011600149335b1cbd4a77b78e33315a0ed10a95b12e7ca48630240897e2d9d24a3b5faaed0579dee7597b401491595675f897504f8945b29d836235bd2fca72a3ad0cae814628973ebcd142d9d6cc92d0b2571b69e5370a98a340c208cb7fb3086f58db9a31401b99e8c658be66134fb9034de1d5c462679270b090702013effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f9f8bc98010116001406ce4b689ba026ffd3a7ca65d1d059546d4b78a000013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c6868f01011600147929ef91997c827bebf60fa608f876ea27523c4700
+    raw_transaction_str: 070100010161015f28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8099c4d5990100011600149335b1cbd4a77b78e33315a0ed10a95b12e7ca48630240897e2d9d24a3b5faaed0579dee7597b401491595675f897504f8945b29d836235bd2fca72a3ad0cae814628973ebcd142d9d6cc92d0b2571b69e5370a98a340c208cb7fb3086f58db9a31401b99e8c658be66134fb9034de1d5c462679270b090702013effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f9f8bc98010116001406ce4b689ba026ffd3a7ca65d1d059546d4b78a000013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c6868f01011600147929ef91997c827bebf60fa608f876ea27523c4700
     network_str: solonet
     transaction: 
 {
@@ -173,7 +171,7 @@ testdata 1:
   "version": 1
 }
 '''
-def decode_raw_tx(raw_tx_str, network_str):
+def decode_raw_tx(raw_transaction_str, network_str):
     tx = {
         "fee": 0,
         "inputs": [],
@@ -184,23 +182,23 @@ def decode_raw_tx(raw_tx_str, network_str):
         "version": 0
     }
     tx['fee'] = 0
-    tx['size'] = len(raw_tx_str) // 2
+    tx['size'] = len(raw_transaction_str) // 2
     length = 0
     offset = 2
-    tx['version'], length = get_uvarint(raw_tx_str[offset:offset+18])
+    tx['version'], length = get_uvarint(raw_transaction_str[offset:offset+18])
     offset = offset + 2 * length
-    tx['time_range'], length = get_uvarint(raw_tx_str[offset:offset+18])
+    tx['time_range'], length = get_uvarint(raw_transaction_str[offset:offset+18])
     offset = offset + 2 * length
-    tx_input_amount, length = get_uvarint(raw_tx_str[offset:offset+8])
+    tx_input_amount, length = get_uvarint(raw_transaction_str[offset:offset+8])
     offset = offset + 2 * length
     prepare_mux_hexstr = (tx_input_amount).to_bytes((tx_input_amount.bit_length() + 7) // 8, 'little').hex()
     prepare_tx_id_hexstr = (tx['version']).to_bytes(8, 'little').hex() + (tx['time_range']).to_bytes(8, 'little').hex()
     for _ in range(tx_input_amount):
-        _, length = get_uvarint(raw_tx_str[offset:offset+18])
+        _, length = get_uvarint(raw_transaction_str[offset:offset+18])
         offset = offset + 2 * length
-        _, length = get_uvarint(raw_tx_str[offset:offset+18])
+        _, length = get_uvarint(raw_transaction_str[offset:offset+18])
         offset = offset + 2 * length
-        input_type = int(raw_tx_str[offset:offset+2], 16)
+        input_type = int(raw_transaction_str[offset:offset+2], 16)
         offset += 2
         if input_type == 0: # issue
             tx_input = {
@@ -213,33 +211,33 @@ def decode_raw_tx(raw_tx_str, network_str):
                 "witness_arguments": []
             }
             tx_input['type'] = "issue"
-            _, length = get_uvarint(raw_tx_str[offset:offset+18])
+            _, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            nonce = raw_tx_str[offset:offset+16]
+            nonce = raw_transaction_str[offset:offset+16]
             offset += 16
             nonce_hash_hexstr = sha3_256(bytes.fromhex(nonce)).hexdigest()
-            tx_input['asset_id'] = raw_tx_str[offset:offset+64]
+            tx_input['asset_id'] = raw_transaction_str[offset:offset+64]
             offset += 64
-            tx_input['amount'], length = get_uvarint(raw_tx_str[offset:offset+18])
+            tx_input['amount'], length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            _, length = get_uvarint(raw_tx_str[offset:offset+18])
+            _, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            asset_definition_size, length = get_uvarint(raw_tx_str[offset:offset+18])
+            asset_definition_size, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            tx_input['asset_definition'] = bytes.fromhex(raw_tx_str[offset:offset+2*asset_definition_size]).decode()
+            tx_input['asset_definition'] = bytes.fromhex(raw_transaction_str[offset:offset+2*asset_definition_size]).decode()
             offset = offset + 2 * asset_definition_size
-            _, length = get_uvarint(raw_tx_str[offset:offset+18])
+            _, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            issuance_program_length, length = get_uvarint(raw_tx_str[offset:offset+18])
+            issuance_program_length, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            tx_input['issuance_program'] = raw_tx_str[offset:offset+2*issuance_program_length]
+            tx_input['issuance_program'] = raw_transaction_str[offset:offset+2*issuance_program_length]
             offset = offset + 2 * issuance_program_length
-            witness_arguments_amount, length = get_uvarint(raw_tx_str[offset:offset+18])
+            witness_arguments_amount, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
             for _ in range(witness_arguments_amount):
-                argument_length, length = get_uvarint(raw_tx_str[offset:offset+18])
+                argument_length, length = get_uvarint(raw_transaction_str[offset:offset+18])
                 offset = offset + 2 * length
-                argument = raw_tx_str[offset:offset+2*argument_length]
+                argument = raw_transaction_str[offset:offset+2*argument_length]
                 offset = offset + 2 * argument_length
                 tx_input['witness_arguments'].append(argument)
             prepare_issue_hexstr = nonce_hash_hexstr + tx_input['asset_id'] + (tx_input['amount']).to_bytes(8, byteorder='little').hex()
@@ -261,36 +259,40 @@ def decode_raw_tx(raw_tx_str, network_str):
                 "witness_arguments": []
             }
             tx_input['type'] = "spend"
-            _, length = get_uvarint(raw_tx_str[offset:offset+18])
+            _, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            source_id = raw_tx_str[offset:offset+64]
+            source_id = raw_transaction_str[offset:offset+64]
             offset += 64
-            tx_input['asset_id'] = raw_tx_str[offset:offset+64]
+            tx_input['asset_id'] = raw_transaction_str[offset:offset+64]
             offset += 64
-            tx_input['amount'], length = get_uvarint(raw_tx_str[offset:offset+18])
+            tx_input['amount'], length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
             tx['fee'] += tx_input['amount']
-            source_positon, length = get_uvarint(raw_tx_str[offset:offset+18])
+            source_positon, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            vmversion, length = get_uvarint(raw_tx_str[offset:offset+18])
+            vmversion, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            control_program_length, length = get_uvarint(raw_tx_str[offset:offset+18])
+            control_program_length, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            tx_input['control_program'] = raw_tx_str[offset:offset+2*control_program_length]
+            tx_input['control_program'] = raw_transaction_str[offset:offset+2*control_program_length]
             offset = offset + 2 * control_program_length
             tx_input['address'] = get_address(tx_input['control_program'], network_str)
-            _, length = get_uvarint(raw_tx_str[offset:offset+18])
+            _, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
-            witness_arguments_amount, length = get_uvarint(raw_tx_str[offset:offset+18])
+            witness_arguments_amount, length = get_uvarint(raw_transaction_str[offset:offset+18])
             offset = offset + 2 * length
+            if witness_arguments_amount == 1:
+                offset = offset + 2
+                tx_input['witness_arguments'] = None
+            else: 
+                for _ in range(witness_arguments_amount):
+                    argument_length, length = get_uvarint(raw_transaction_str[offset:offset+18])
+                    offset = offset + 2 * length
+                    argument = raw_transaction_str[offset:offset+2*argument_length]
+                    offset = offset + 2 * argument_length
+                    tx_input['witness_arguments'].append(argument)
             tx_input['spent_output_id'] = get_spend_output_id(source_id, tx_input['asset_id'], tx_input['amount'], source_positon, vmversion, tx_input['control_program'])
             tx_input['input_id'] = get_input_id(tx_input['spent_output_id'])
-            for _ in range(witness_arguments_amount):
-                argument_length, length = get_uvarint(raw_tx_str[offset:offset+18])
-                offset = offset + 2 * length
-                argument = raw_tx_str[offset:offset+2*argument_length]
-                offset = offset + 2 * argument_length
-                tx_input['witness_arguments'].append(argument)
             tx['inputs'].append(tx_input)
             prepare_mux_hexstr += tx_input['input_id'] + tx_input['asset_id'] + (tx_input['amount']).to_bytes(8, byteorder='little').hex() + '0000000000000000'
             prepare_mux_hexstr += '0100000000000000' + '0151'
@@ -306,17 +308,17 @@ def decode_raw_tx(raw_tx_str, network_str):
                 "witness_arguments": []
             }
             tx_input['type'] = "coinbase"
-            arbitrary_length, length = get_uvarint(raw_tx_str[offset:offset+18])
-            prepare_coinbase_input_id_hexstr = raw_tx_str[offset:offset+2*length]
+            arbitrary_length, length = get_uvarint(raw_transaction_str[offset:offset+18])
+            prepare_coinbase_input_id_hexstr = raw_transaction_str[offset:offset+2*length]
             offset = offset + 2 * length
-            tx_input['arbitrary'] = raw_tx_str[offset:offset+2*arbitrary_length]
+            tx_input['arbitrary'] = raw_transaction_str[offset:offset+2*arbitrary_length]
             prepare_coinbase_input_id_hexstr += tx_input['arbitrary']
             offset = offset + 2 * arbitrary_length
             tx_input['input_id'] = get_coinbase_input_id(prepare_coinbase_input_id_hexstr)
             offset = offset + 2
             tx['inputs'].append(tx_input)
             prepare_mux_hexstr += tx_input['input_id'] + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
-    tx_output_amount, length = get_uvarint(raw_tx_str[offset:offset+18])
+    tx_output_amount, length = get_uvarint(raw_transaction_str[offset:offset+18])
     offset = offset + 2 * length
     prepare_tx_id_hexstr += (tx_output_amount).to_bytes((tx_output_amount.bit_length() + 7) // 8, 'little').hex()
     for i in range(tx_output_amount):
@@ -331,27 +333,27 @@ def decode_raw_tx(raw_tx_str, network_str):
             "type": ""
         }
         tx_output['position'] = i
-        _, length = get_uvarint(raw_tx_str[offset:offset+18])
+        _, length = get_uvarint(raw_transaction_str[offset:offset+18])
         offset = offset + 2 * length
-        _, length = get_uvarint(raw_tx_str[offset:offset+18])
+        _, length = get_uvarint(raw_transaction_str[offset:offset+18])
         offset = offset + 2 * length
-        tx_output['asset_id'] = raw_tx_str[offset:offset+64]
+        tx_output['asset_id'] = raw_transaction_str[offset:offset+64]
         offset = offset + 64
-        tx_output['amount'], length = get_uvarint(raw_tx_str[offset:offset+18])
+        tx_output['amount'], length = get_uvarint(raw_transaction_str[offset:offset+18])
         if tx_input['type'] == "coinbase":
             prepare_mux_hexstr = prepare_mux_hexstr + (tx_output['amount']).to_bytes(8, byteorder='little').hex() + '0000000000000000' + '0100000000000000' + '0151'
             mux_id_hexstr = get_mux_id(prepare_mux_hexstr)
         offset = offset + 2 * length
         if tx_output['asset_id'] == 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff':
             tx['fee'] -= tx_output['amount']
-        _, length = get_uvarint(raw_tx_str[offset:offset+18])
+        _, length = get_uvarint(raw_transaction_str[offset:offset+18])
         offset = offset + 2 * length
-        control_program_length, length = get_uvarint(raw_tx_str[offset:offset+18])
+        control_program_length, length = get_uvarint(raw_transaction_str[offset:offset+18])
         offset = offset + 2 * length
-        tx_output['control_program'] = raw_tx_str[offset:offset+2*control_program_length]
+        tx_output['control_program'] = raw_transaction_str[offset:offset+2*control_program_length]
         offset = offset + 2 * control_program_length
         tx_output['address'] = get_address(tx_output['control_program'], network_str)
-        _, length = get_uvarint(raw_tx_str[offset:offset+18])
+        _, length = get_uvarint(raw_transaction_str[offset:offset+18])
         offset = offset + 2 * length
         prepare_output_id_hexstr = mux_id_hexstr + tx_output['asset_id'] + (tx_output['amount']).to_bytes(8, byteorder='little').hex() + (i).to_bytes(8, byteorder='little').hex() + '0100000000000000' + (control_program_length).to_bytes((control_program_length.bit_length() + 7) // 8, 'little').hex() + tx_output['control_program']
         tx_output['id'] = get_output_id(prepare_output_id_hexstr)
@@ -361,4 +363,4 @@ def decode_raw_tx(raw_tx_str, network_str):
     if tx_input['type'] == "coinbase":
         tx['fee'] = 0
     tx['tx_id'] = get_tx_id(prepare_tx_id_hexstr)
-    return tx
+    return tx
\ No newline at end of file