OSDN Git Service

add segwit_addr.py
authorChengcheng Zhang <943420582@qq.com>
Mon, 7 Jan 2019 05:48:30 +0000 (13:48 +0800)
committerChengcheng Zhang <943420582@qq.com>
Mon, 7 Jan 2019 05:48:30 +0000 (13:48 +0800)
app/api/__init__.py
app/api/resources.py
app/model/receiver.py
app/model/segwit_addr.py [new file with mode: 0644]

index 9f74c94..895d0b1 100644 (file)
@@ -16,6 +16,7 @@ from app.api.resources import Xprv_To_Xpub
 from app.api.resources import Xprv_To_Child_Xprv
 from app.api.resources import Xpub_To_Child_Xpub
 from app.api.resources import Create_P2WPKH_Program
+from app.api.resources import Create_Address
 
 blueprint = Blueprint('api', __name__, url_prefix='/api/v1')
 api = Api(blueprint)
@@ -34,4 +35,5 @@ api.add_resource(Xprv_Sign, '/xprv_sign')
 api.add_resource(Xprv_To_Xpub, '/xprv_to_xpub')
 api.add_resource(Xprv_To_Child_Xprv, '/xprv_to_child_xprv')
 api.add_resource(Xpub_To_Child_Xpub, '/xpub_to_child_xpub')
-api.add_resource(Create_P2WPKH_Program, '/create_P2WPKH_program')
\ No newline at end of file
+api.add_resource(Create_P2WPKH_Program, '/create_P2WPKH_program')
+api.add_resource(Create_Address, '/create_address')
\ No newline at end of file
index b97ceb3..90ca20b 100644 (file)
@@ -1,4 +1,3 @@
-# from flask_restplus import inputs
 from flask_restful import inputs
 from flask_restful import Resource
 from flask_restful import reqparse
@@ -18,6 +17,7 @@ from app.model.key import xprv_sign
 from app.model.key import xprv_to_child_xprv
 from app.model.key import xpub_to_child_xpub
 from app.model.receiver import create_P2WPKH_program
+from app.model.receiver import create_address
 
 parser = reqparse.RequestParser()
 parser.add_argument('private_key_str', type=str)
@@ -33,6 +33,8 @@ parser.add_argument('path_list', type=str, action='append')
 parser.add_argument('account_index_int', type=int)
 parser.add_argument('address_index_int', type=int)
 parser.add_argument('change_bool', type=inputs.boolean)
+parser.add_argument('control_program_str', type=str)
+parser.add_argument('network_str', type=str)
 
 class Hello(Resource):
 
@@ -158,4 +160,13 @@ class Create_P2WPKH_Program(Resource):
         change = args.get('change_bool')
         xpub = args.get('xpub_str')
         control_program = create_P2WPKH_program(account_index, address_index, change, xpub)
-        return control_program
\ No newline at end of file
+        return control_program
+
+class Create_Address(Resource):
+
+    def post(self):
+        args = parser.parse_args()
+        control_program = args.get('control_program_str')
+        network = args.get('network_str')
+        address = create_address(control_program, network)
+        return address
\ No newline at end of file
index a88572d..598f06d 100644 (file)
@@ -1,5 +1,6 @@
 import hashlib
 from app.model.key import *
+from app.model import segwit_addr
 
 # get_path_from_index create xpub path from account key index and current address index
 # Please attention:
@@ -13,13 +14,10 @@ def get_path_from_index(account_index_int, address_index_int, change_bool):
     path_list = ['2c000000', '99000000']
     account_index_str = (account_index_int).to_bytes(4, byteorder='little').hex()
     path_list.append(account_index_str)
-    print("change_bool:", type(change_bool), change_bool)
-    if change_bool == True:
+    if change_bool:
         branch_str = (1).to_bytes(4, byteorder='little').hex()
-        print("true")
-    elif change_bool == False:
+    else:
         branch_str = (0).to_bytes(4, byteorder='little').hex()
-        print("false")
     path_list.append(branch_str)
     address_index_str = (address_index_int).to_bytes(4, byteorder='little').hex()
     path_list.append(address_index_str)
@@ -38,4 +36,25 @@ def create_P2WPKH_program(account_index_int, address_index_int, change_bool, xpu
     public_key_hash_str = ripemd160.hexdigest()
     control_program_str = '0014' + public_key_hash_str
 
-    return control_program_str
\ No newline at end of file
+    return control_program_str
+
+def create_address(control_program_str, network_str):
+    # path_list = get_path_from_index(account_index_int, address_index_int, change_bool)
+    # child_xpub_str = xpub_to_child_xpub(xpub_str, path_list)
+    # child_public_key_str = xpub_to_public_key(child_xpub_str)
+    # child_public_key_byte = bytes.fromhex(child_public_key_str)
+    
+    # ripemd160 = hashlib.new('ripemd160')
+    # ripemd160.update(child_public_key_byte)
+    public_key_hash_str = control_program_str[4:]
+    # control_program_str = '0014' + public_key_hash_str
+
+    if network_str == 'mainnet':
+        hrp = 'bm'
+    elif network_str == 'testnet':
+        hrp = 'tm'
+    elif network_str == 'solonet':
+        hrp = 'sm'
+    address_str = segwit_addr.encode(hrp, 0, bytes.fromhex(public_key_hash_str))
+
+    return address_str
\ No newline at end of file
diff --git a/app/model/segwit_addr.py b/app/model/segwit_addr.py
new file mode 100644 (file)
index 0000000..e0df3b6
--- /dev/null
@@ -0,0 +1,123 @@
+# Copyright (c) 2017 Pieter Wuille
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+"""Reference implementation for Bech32 and segwit addresses."""
+
+
+CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+
+
+def bech32_polymod(values):
+    """Internal function that computes the Bech32 checksum."""
+    generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
+    chk = 1
+    for value in values:
+        top = chk >> 25
+        chk = (chk & 0x1ffffff) << 5 ^ value
+        for i in range(5):
+            chk ^= generator[i] if ((top >> i) & 1) else 0
+    return chk
+
+
+def bech32_hrp_expand(hrp):
+    """Expand the HRP into values for checksum computation."""
+    return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
+
+
+def bech32_verify_checksum(hrp, data):
+    """Verify a checksum given HRP and converted data characters."""
+    return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1
+
+
+def bech32_create_checksum(hrp, data):
+    """Compute the checksum values given HRP and data."""
+    values = bech32_hrp_expand(hrp) + data
+    polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
+    return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
+
+
+def bech32_encode(hrp, data):
+    """Compute a Bech32 string given HRP and data values."""
+    combined = data + bech32_create_checksum(hrp, data)
+    return hrp + '1' + ''.join([CHARSET[d] for d in combined])
+
+
+def bech32_decode(bech):
+    """Validate a Bech32 string, and determine HRP and data."""
+    if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
+            (bech.lower() != bech and bech.upper() != bech)):
+        return (None, None)
+    bech = bech.lower()
+    pos = bech.rfind('1')
+    if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
+        return (None, None)
+    if not all(x in CHARSET for x in bech[pos+1:]):
+        return (None, None)
+    hrp = bech[:pos]
+    data = [CHARSET.find(x) for x in bech[pos+1:]]
+    if not bech32_verify_checksum(hrp, data):
+        return (None, None)
+    return (hrp, data[:-6])
+
+
+def convertbits(data, frombits, tobits, pad=True):
+    """General power-of-2 base conversion."""
+    acc = 0
+    bits = 0
+    ret = []
+    maxv = (1 << tobits) - 1
+    max_acc = (1 << (frombits + tobits - 1)) - 1
+    for value in data:
+        if value < 0 or (value >> frombits):
+            return None
+        acc = ((acc << frombits) | value) & max_acc
+        bits += frombits
+        while bits >= tobits:
+            bits -= tobits
+            ret.append((acc >> bits) & maxv)
+    if pad:
+        if bits:
+            ret.append((acc << (tobits - bits)) & maxv)
+    elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
+        return None
+    return ret
+
+
+def decode(hrp, addr):
+    """Decode a segwit address."""
+    hrpgot, data = bech32_decode(addr)
+    if hrpgot != hrp:
+        return (None, None)
+    decoded = convertbits(data[1:], 5, 8, False)
+    if decoded is None or len(decoded) < 2 or len(decoded) > 40:
+        return (None, None)
+    if data[0] > 16:
+        return (None, None)
+    if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
+        return (None, None)
+    return (data[0], decoded)
+
+
+def encode(hrp, witver, witprog):
+    """Encode a segwit address."""
+    ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
+    if decode(hrp, ret) == (None, None):
+        return None
+    return ret
\ No newline at end of file