def secure_mnemonic(entropy=0, num_bits=128): '''Generates a mnemonic phrase using the number of bits''' # if we have more than 128 bits, just mask everything but the last 128 bits if len(bin(entropy)) > num_bits + 2: entropy &= (1 << num_bits) - 1 # xor some random bits with the entropy that was passed in preseed = randbits(num_bits) ^ entropy # convert the number to big-endian s = int_to_big_endian(preseed, 16) # 1 extra bit for checksum is needed per 32 bits checksum_bits_needed = num_bits // 32 # the checksum is the sha256's first n bits. At most this is 8 checksum = sha256(s)[0] >> (8 - checksum_bits_needed) # we concatenate the checksum to the preseed total = (preseed << checksum_bits_needed) | checksum # now we get the mnemonic passphrase mnemonic = [] # now group into groups of 11 bits for _ in range((num_bits + checksum_bits_needed) // 11): # grab the last 11 bits current = total & ((1 << 11) - 1) # insert the correct word at the front mnemonic.insert(0, WORD_LIST[current]) # shift by 11 bits so we can move to the next set total >>= 11 # return the mnemonic phrase by putting spaces between return ' '.join(mnemonic)
def from_mnemonic(cls, mnemonic, password=b'', path=b'm', testnet=False): binary_seed = bytearray() words = mnemonic.split() if len(words) not in (12, 15, 18, 21, 24): raise ValueError('you need 12, 15, 18, 21, or 24 words') number = 0 for word in words: index = WORD_LOOKUP[word] number = (number << 11) + index # checksum is the last n bits where n = (# of words / 3) checksum_bits_length = len(words) // 3 checksum = number & ((1 << checksum_bits_length) - 1) bits_to_ignore = (8 - checksum_bits_length) % 8 data_num = number >> checksum_bits_length data = data_num.to_bytes(checksum_bits_length * 4, 'big') computed_checksum = sha256(data)[0] >> bits_to_ignore if checksum != computed_checksum: raise ValueError('words fail checksum: {}'.format(words)) normalized_words = [] for word in words: normalized_words.append(WORD_LIST[WORD_LOOKUP[word]]) normalized_mnemonic = ' '.join(normalized_words) seed = PBKDF2( normalized_mnemonic, b'mnemonic' + password, iterations=PBKDF2_ROUNDS, macmodule=hmac, digestmodule=sha512, ).read(64) return cls.from_seed(seed, path, testnet=testnet)
def secure_mnemonic(entropy=0, num_bits=128): # if we have more than 128 bits, just mask everything but the last 128 bits if len(bin(entropy)) > num_bits + 2: entropy &= (1 << num_bits) - 1 preseed = randbits(num_bits) ^ entropy s = preseed.to_bytes(16, 'big') bits_needed = num_bits // 32 checksum = sha256(s)[0] >> (8 - bits_needed) total = (preseed << bits_needed) + checksum mnemonic = [] # now group into groups of 11 bits for _ in range((num_bits + bits_needed) // 11): # last 11 bits current = total & ((1 << 11) - 1) mnemonic.insert(0, WORD_LIST[current]) total >>= 11 return ' '.join(mnemonic)
def from_mnemonic(cls, mnemonic, password=b'', path='m', testnet=False): '''Returns a HDPrivateKey object from the mnemonic.''' # split the mnemonic into words with .split() words = mnemonic.split() # check that there are 12, 15, 18, 21 or 24 words # if not, raise a ValueError if len(words) not in (12, 15, 18, 21, 24): raise ValueError('you need 12, 15, 18, 21, or 24 words') # calculate the number number = 0 # each word is 11 bits for word in words: # get the number that the word represents using WORD_LOOKUP index = WORD_LOOKUP[word] # left-shift the number by 11 bits and bitwise-or the index number = (number << 11) | index # checksum is the last n bits where n = (# of words / 3) checksum_bits_length = len(words) // 3 # grab the checksum bits checksum = number & ((1 << checksum_bits_length) - 1) # get the actual number by right-shifting by the checksum bits length data_num = number >> checksum_bits_length # convert the number to big-endian data = int_to_big_endian(data_num, checksum_bits_length * 4) # the one byte we get is from sha256 of the data, shifted by # 8 - the number of bits we need for the checksum computed_checksum = sha256(data)[0] >> (8 - checksum_bits_length) # check that the checksum is correct or raise ValueError if checksum != computed_checksum: raise ValueError('words fail checksum: {}'.format(words)) # normalize in case we got a mnemonic that's just the first 4 letters normalized_words = [] for word in words: normalized_words.append(WORD_LIST[WORD_LOOKUP[word]]) normalized_mnemonic = ' '.join(normalized_words) # salt is b'mnemonic' + password salt = b'mnemonic' + password # the seed is the hmac_sha512_kdf with normalized mnemonic and salt seed = hmac_sha512_kdf(normalized_mnemonic, salt) # return the HDPrivateKey at the path specified return cls.from_seed(seed, testnet=testnet).traverse(path)
def from_mnemonic(cls, mnemonic, password=b'', path='m', testnet=False): words = mnemonic.split() if len(words) not in (12, 15, 18, 21, 24): raise ValueError('you need 12, 15, 18, 21, or 24 words') number = 0 for word in words: index = WORD_LOOKUP[word] number = (number << 11) | index checksum_bits_length = len(words) // 3 checksum = number & ((1 << checksum_bits_length) - 1) data_num = number >> checksum_bits_length data = int_to_big_endian(data_num, checksum_bits_length * 4) computed_checksum = sha256(data)[0] >> (8 - checksum_bits_length) if checksum != computed_checksum: raise ValueError('words fail checksum: {}'.format(words)) normalized_words = [] for word in words: normalized_words.append(WORD_LIST[WORD_LOOKUP[word]]) normalized_mnemonic = ' '.join(normalized_words) salt = b'mnemonic' + password seed = hmac_sha512_kdf(normalized_mnemonic, salt) return cls.from_seed(seed, testnet=testnet).traverse(path)
def evaluate(self, z, witness): # create a copy as we may need to add to this list if we have a # RedeemScript cmds = self.cmds[:] stack = [] altstack = [] while len(cmds) > 0: cmd = cmds.pop(0) if type(cmd) == int: # do what the opcode says operation = OP_CODE_FUNCTIONS[cmd] if cmd in (99, 100): # op_if/op_notif require the cmds array if not operation(stack, cmds): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False elif cmd in (107, 108): # op_toaltstack/op_fromaltstack require the altstack if not operation(stack, altstack): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False elif cmd in (172, 173, 174, 175): # these are signing operations, they need a sig_hash # to check against if not operation(stack, z): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False else: if not operation(stack): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False else: # add the cmd to the stack stack.append(cmd) # p2sh rule. if the next three cmds are: # OP_HASH160 <20 byte hash> OP_EQUAL this is the RedeemScript # OP_HASH160 == 0xa9 and OP_EQUAL == 0x87 if len(cmds) == 3 and cmds[0] == 0xa9 \ and type(cmds[1]) == bytes and len(cmds[1]) == 20 \ and cmds[2] == 0x87: redeem_script = encode_varint(len(cmd)) + cmd # we execute the next three opcodes cmds.pop() h160 = cmds.pop() cmds.pop() if not op_hash160(stack): return False stack.append(h160) if not op_equal(stack): return False # final result should be a 1 if not op_verify(stack): LOGGER.info('bad p2sh h160') return False # hashes match! now add the RedeemScript redeem_script = encode_varint(len(cmd)) + cmd stream = BytesIO(redeem_script) cmds.extend(Script.parse(stream).cmds) # witness program version 0 rule. if stack cmds are: # 0 <20 byte hash> this is p2wpkh # tag::source3[] if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 20: # <1> h160 = stack.pop() stack.pop() cmds.extend(witness) cmds.extend(p2pkh_script(h160).cmds) # end::source3[] # witness program version 0 rule. if stack cmds are: # 0 <32 byte hash> this is p2wsh # tag::source6[] if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 32: s256 = stack.pop() # <1> stack.pop() # <2> cmds.extend(witness[:-1]) # <3> witness_script = witness[-1] # <4> if s256 != sha256(witness_script): # <5> print('bad sha256 {} vs {}'.format (s256.hex(), sha256(witness_script).hex())) return False stream = BytesIO(encode_varint(len(witness_script)) + witness_script) witness_script_cmds = Script.parse(stream).cmds # <6> cmds.extend(witness_script_cmds) # end::source6[] if len(stack) == 0: return False if stack.pop() == b'': return False return True
def evaluate(self, z, witness): # create a copy as we may need to add to this list if we have a # RedeemScript instructions = self.instructions[:] stack = [] altstack = [] while len(instructions) > 0: instruction = instructions.pop(0) if type(instruction) == int: # do what the opcode says operation = OP_CODE_FUNCTIONS[instruction] if instruction in (99, 100): # op_if/op_notif require the instructions array if not operation(stack, instructions): LOGGER.info('bad op: {}'.format( OP_CODE_NAMES[instruction])) return False elif instruction in (107, 108): # op_toaltstack/op_fromaltstack require the altstack if not operation(stack, altstack): LOGGER.info('bad op: {}'.format( OP_CODE_NAMES[instruction])) return False elif instruction in (172, 173, 174, 175): # these are signing operations, they need a sig_hash # to check against if not operation(stack, z): LOGGER.info('bad op: {}'.format( OP_CODE_NAMES[instruction])) return False else: if not operation(stack): LOGGER.info('bad op: {}'.format( OP_CODE_NAMES[instruction])) return False else: # add the instruction to the stack stack.append(instruction) # p2sh rule. if the next three instructions are: # OP_HASH160 <20 byte hash> OP_EQUAL this is the RedeemScript # OP_HASH160 == 0xa9 and OP_EQUAL == 0x87 if len(instructions) == 3 and instructions[0] == 0xa9 \ and type(instructions[1]) == bytes and len(instructions[1]) == 20 \ and instructions[2] == 0x87: redeem_script = encode_varint( len(instruction)) + instruction # we execute the next three opcodes instructions.pop() h160 = instructions.pop() instructions.pop() if not op_hash160(stack): return False stack.append(h160) if not op_equal(stack): return False # final result should be a 1 if not op_verify(stack): LOGGER.info('bad p2sh h160') return False # hashes match! now add the RedeemScript redeem_script = encode_varint( len(instruction)) + instruction stream = BytesIO(redeem_script) instructions.extend(Script.parse(stream).instructions) # witness program version 0 rule. if stack instructions are: # 0 <20 byte hash> this is p2wpkh if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 20: h160 = stack.pop() stack.pop() instructions.extend(witness) instructions.extend(p2pkh_script(h160).instructions) # witness program version 0 rule. if stack instructions are: # 0 <32 byte hash> this is p2wsh if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 32: h256 = stack.pop() stack.pop() instructions.extend(witness[:-1]) witness_script = witness[-1] if h256 != sha256(witness_script): LOGGER.info('bad sha256 {} vs {}'.format( h256.hex(), sha256(witness_script).hex())) return False # hashes match! now add the Witness Script stream = BytesIO( encode_varint(len(witness_script)) + witness_script) witness_script_instructions = Script.parse( stream).instructions instructions.extend(witness_script_instructions) if len(stack) == 0: return False if stack.pop() == b'': return False return True
def sha256(self): '''Return the sha256 of the serialized script (without length)''' return sha256(self.raw_serialize())
def cipher(self, other_point: S256Point) -> CPCipher: '''Returns a cipher and the prefix needed by the owner of the private key to decrypt this message''' shared_secret = sha256((self.secret * other_point).sec()) return CPCipher(shared_secret)
from sys import argv from os.path import isfile, realpath, dirname from helper import sha256 from flask import Flask from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from flask_sqlalchemy import SQLAlchemy # Local from config import Config path = dirname(realpath(__file__)) secret = "%s/app.secret" % path if not isfile(secret): with open(secret, "w") as f: f.write(sha256()) app = Flask(__name__, static_url_path="/assets") with open(secret, "r") as f: app.secret_key = f.read() app.config.from_object(Config) db = SQLAlchemy(app) migrate = Migrate(app, db) manager = None if len(argv) > 1: manager = Manager(app) manager.add_command("db", MigrateCommand)
def evaluate(self, z, witness): # create a copy as we may need to add to this list if we have a # RedeemScript cmds = self.cmds[:] stack = [] altstack = [] while len(cmds) > 0: cmd = cmds.pop(0) if type(cmd) == int: # do what the opcode says # retrieving the function in op.py corresponding to the opcode operation = OP_CODE_FUNCTIONS[cmd] if cmd in (99, 100): # op_if/op_notif require the cmds array if not operation(stack, cmds): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False elif cmd in (107, 108): # op_toaltstack/op_fromaltstack require the altstack if not operation(stack, altstack): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False elif cmd in (172, 173, 174, 175): # these are signing operations, they need a sig_hash # to check against if not operation(stack, z): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False else: if not operation(stack): LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd])) return False else: # add the cmd to the stack stack.append(cmd) # Determine whether this is a p2sh: # To do so, you need to look at the next three items in the command set. # Are there only three items remaining in the command set and are theY: # 0xa9 --op_hash160, 20 bytes--for the script hash and 0x87--op_equal? if len(cmds) == 3 and cmds[0] == 0xa9 and type(cmds[1]) == bytes and len(cmds[1]) == 20 and cmds[2] == 0x87: # <1> cmds.pop() # <2> h160 = cmds.pop() cmds.pop() if not op.op_hash160(stack): # <3> return False stack.append(h160) if not op.op_equal(stack): return False if not op.op_verify(stack): # <4> LOGGER.info('bad p2sh h160') return False redeem_script = encode_varint(len(cmd)) + cmd # <5> stream = BytesIO(redeem_script) cmds.extend(Script.parse(stream).cmds) # <6> # Determine whether this is a p2wpkh. # To do so, you need to look at the stack (remember focus on the stack now, not the command set). # Are there only two items on the stack? is the first b'' and the second 20 bytes? # The 20 bytes will be the hash of the witness field. # If so, then use the witness field and the hash on the stack to build a p2pkh command set. if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 20: h160 = stack.pop() stack.pop() # witness should be two items, the signature and the public key (in bytes not BASE58) cmds.extend(witness) # the build out the command set with the p2pkh commands cmds.extend(p2pkh_script(h160).cmds) # now we have the p2pkh command set and the script evaluation proceeds... # Determine whether this is a p2wsh: # Does stack have just two items, b'' and a 32 byte hash-which hash is the witness script hash. # If so, check that the hash of the witness script equals the witness script hash # that is already on the stack. If so, build a command set starting with the witness filed items # and then parse the witness script. Append the parsed witness script items to the command set. # The p2wsh is often used for the segwit form of the m of n multisig. if len(stack) == 2 and stack[0] == b'' and type(stack[1]) == bytes and len(stack[1])==32: s256 = stack.pop() stack.pop() witness_script = witness[-1] if s256 != sha256(witness_script): print('bad sha256 {} vs {}'.format(s256.hex(), sha256(witness_script).hex())) return False # If the wintess script checks out then add the witness fields to the command set--leaving the # witness script item to be parsed still cmds.extend(witness[:-1]) # Parse the witness script--prepare it as a raw script and make into a stream first. witness_script = encode_varint(len(witness_script)) + witness_script witness_stream = BytesIO(witness_script) witness_script_cmds = Script.parse(witness_stream).cmds # Add the witness script items to the command set--these should be the script_pub_key # items from a regular p2sh script_pub_key--which would be the m of n multisig. cmds.extend(witness_script_cmds) if len(stack) == 0: return False if stack.pop() == b'': return False return True
def SHA256(*args): return sha256(b''.join(args))
def routing(): global total_bytes_routed_main print("----Route Mode----") prev_hop = get_peer(peers, 'mst8broiaX4PFMFNbjfrBnMSnrVF42Jgd7') prev_hop_channel = get_channel(prev_hop, channels) sym_key_prev_hop = prev_hop.sym_key wallet_balance = get_total_channel_balance(channels) local_balance_DC = get_channel_balance(channels[0]) local_balance_DA = get_channel_balance(channels[1]) totalBalance.set(wallet_balance) channel_A_local.set(local_balance_DA) channel_C_local.set(local_balance_DC) while True: # receive header received_header = json.loads((prev_hop.receive()).decode()) commitment_tx_prev_hop = Tx.parse(BytesIO(bytes.fromhex(received_header['commitment_tx']))) H = check_htlc_and_get_secret_hash(node, commitment_tx_prev_hop, prev_hop_channel) num_packets = received_header['num_packets'] packet_size = received_header['packet_size'] num_bytes = num_packets*packet_size #num_kilobytes = int(num_packets*packet_size/1000) prev_hop.send(b'header ACK') #receive packets packet_payloads = [] for i in range(num_packets): packet_payloads.append(prev_hop.receive()) prev_hop.send(b'packet ACK') cost_paid = int(route_cost(received_header['route'], num_bytes)) #adapt header for next hop header = received_header header['route'] = received_header['route'][1:] cost_to_pay = int(route_cost(header['route'], num_bytes)) next_hop = get_peer(peers, header['route'][0][0]) next_hop_channel = get_channel(next_hop, channels) commitment_tx_next_hop = new_commitment_tx(node, next_hop_channel, cost_to_pay, H) header['commitment_tx'] = str(commitment_tx_next_hop.serialize().hex()) #send header next_hop.send(str.encode(json.dumps(header))) if(next_hop.receive()==b'header ACK'): for i in range(num_packets): next_hop.send(packet_payloads[i]) next_hop.receive() reply = json.loads(next_hop.receive().decode()) commitment_tx_next_hop = Tx.parse(BytesIO(bytes.fromhex(reply['commitment_tx']))) revealed_secret = reply['secret'] if(not (H == None) and (sha256(str.encode(str(revealed_secret))) == H)): print("I can sign the htlc output with the secret") next_hop_channel.pay(cost_to_pay) #sign the commitment tx commitment_tx_prev_hop.tx_ins[0].script_sig = get_script_sig(commitment_tx_prev_hop, node.private_key) reply = {"commitment_tx": str(commitment_tx_prev_hop.serialize().hex()), "secret": revealed_secret} prev_hop.send(str.encode(json.dumps(reply))) prev_hop_channel.paid(cost_paid) for c in channels: print(c) total_bytes_routed_main += num_bytes total_bytes_routed.set(total_bytes_routed_main) wallet_balance = get_total_channel_balance(channels) local_balance_DC = get_channel_balance(channels[0]) local_balance_DA = get_channel_balance(channels[1]) totalBalance.set(wallet_balance) channel_A_local.set(local_balance_DA) channel_C_local.set(local_balance_DC) print("Total Balance: "+str(wallet_balance)) else: print("Cannot unlock HTLC")
def evaluate(self, z, witness, version=None, locktime=None, sequence=None): # get a copy of the commands array. cmds = self.cmds.copy() stack = [] altstack = [] # execute until commands array is empty. while len(cmds) > 0: cmd = cmds.pop(0) print("cmd", cmd) # if command is an opcode. if type(cmd) == int: # get the function that executes the opcode from the OP_CODE_FUNCTIONS array. operation = OP_CODE_FUNCTIONS[cmd] # 99 and 100 are OP_IF and OP_NOTIF. They require manipulations of the cmds array based on # the top element of the stack. if cmd in (99, 100): # if executing the opcode returns False (fails) if not operation(stack, cmds): LOGGER.info(f"bad op: {OP_CODE_NAMES[cmd]}") return False # 107 and 108 are OP_TOALTSTACK and OP_FROMALTSTACK respectively. They move stack elements # to an alternate stack (altstack) elif cmd in (107, 108): # if executing the opcode returns False (fails) if not operation(stack, altstack): LOGGER.info(f"bad op: {OP_CODE_NAMES[cmd]}") return False # 172, 173, 174 and 175 are OP_CHECKSIG, OP_CHECKSIGVERIFY, OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY # all require the signature hash z for validation. elif cmd in (172, 173, 174, 175): # if executing the opcode returns False (fails) if not operation(stack, z): LOGGER.info(f"bad op: {OP_CODE_NAMES[cmd]}") return False # 177 is OP_CHECKLOCKTIMEVERIFY. Requires locktime and sequence. elif cmd == 177: # if executing the opcode returns False (fails) if not operation(stack, locktime, sequence): LOGGER.info(f"bad op: {OP_CODE_NAMES[cmd]}") return False # 177 is OP_CHECKSEQUENCEVERIFY. Requires sequence and version. elif cmd == 178: # if executing the opcode returns False (fails) if not operation(stack, version, sequence): LOGGER.info(f"bad op: {OP_CODE_NAMES[cmd]}") return False else: # if executing the opcode returns False (fails) if not operation(stack): LOGGER.info(f"bad op: {OP_CODE_NAMES[cmd]}") return False # if cmd is not an opcode, it's an element. We push it to the stack. else: stack.append(cmd) # We check if the commands follow the p2wsh special rule. if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 32: # The top element is the sha256 hash of the WitnessScript. s256 = stack.pop() # The second element is the witness version. stack.pop() # Everything but the WitnessScript is added to the command set. cmds.extend(witness[:-1]) witness_script = witness[-1] s256_calculated = sha256(witness_script) if s256 != s256_calculated: print( f"Bad sha256 {s256.hex()} vs. {s256_calculated.hex()}" ) return False stream = BytesIO( encode_varint(len(witness_script)) + witness_script) witness_script_cmds = Script.parse(stream).cmds cmds.extend(witness_script_cmds) # We check if the commands follow the p2wpkh special rule - page 235. if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 20: h160 = stack.pop() stack.pop() cmds.extend(witness) cmds.extend(p2pkh_script(h160).cmds) # we check if next commands form the pattern that executes the special p2sh rule - page 152 and 156. # if that is the case, the last cmd appended would be the RedeemScript, which is an element. # That's why we check for the next 3 commands only. # Specifically, we check that they are: OP_HASH160 (0xa9), a hash element and OP_EQUAL(0x87). if len(cmds) == 3 and cmds[0] == 0xa9 and type( cmds[1]) == bytes and len( cmds[1]) == 20 and cmds[2] == 0x87: # we run the sequence manually. cmds.pop() # the only value we need to save is the hash, the other two we know are OP_HASH160 and OP_EQUAL. h160 = cmds.pop() cmds.pop() # first we perform the op_hash160 on the current stack, which hashes the top element of the stack. if not op_hash160(stack): return False # then we push the hash160 we got in the commands to the stack. stack.append(h160) # next we perform an op_equal, which compares the 2 top most elements of the stack. if not op_equal(stack): return False # next we need to check if the element left on the stack is a 1, which is what op_verify does. if not op_verify(stack): LOGGER.info('bad p2sh h160') return False # if we got to this point, we know cmd is the RedeemScrtipt. # to be able to parse it, we need to prepend its length. redeem_script = encode_varint(len(cmd)) + cmd # we convert the script into a stream of bytes. stream = BytesIO(redeem_script) # we get the parsed script parsed_script = Script.parse(stream) # we extend the commands set with the commands from the parsed RedeemScript. cmds.extend(parsed_script.cmds) # if stack is empty after running all the commands, we fail the script returning False. if len(stack) == 0: return False # if the stack's top element is an empty byte, which is how the stack stores a 0, we fail the script. if stack.pop() == b'': return False # any other result means the script is valid. return True
def send_packets(): global packet_size_main global num_packets_main global total_bytes_sent_main global go # destination (C's address (or rather, the Gateways BTC address)) destination = 'n1weDdde5xXLfPeutESLaG8swr5jLCqz72' sym_key_dest = get_peer(peers, destination).sym_key wallet_balance = get_total_channel_balance(channels) local_balance_AB = get_channel_balance(channels[0]) local_balance_AD = get_channel_balance(channels[1]) totalBalance.set(wallet_balance) channel_B_local.set(local_balance_AB) channel_D_local.set(local_balance_AD) while True: #packet_size_freeze = packet_size_main*1000 #convert from kB to B #num_kilobytes = int(num_bytes/1000) if (packet_size_main > 0 and num_packets_main > 0 and go == True): packet_size_freeze = packet_size_main num_packets_freeze = num_packets_main num_bytes = packet_size_freeze * num_packets_freeze # find routes routes = [[[ 'mfwnjj1Jbd1uwXbj5Q4FUjmkEcGqQQsYDn', prices['mfwnjj1Jbd1uwXbj5Q4FUjmkEcGqQQsYDn'] ], [ 'n1weDdde5xXLfPeutESLaG8swr5jLCqz72', prices['n1weDdde5xXLfPeutESLaG8swr5jLCqz72'] ]], [[ 'mmqrZXdvAi8mcjvXGJX2eJdA37kWXmCWjW', prices['mmqrZXdvAi8mcjvXGJX2eJdA37kWXmCWjW'] ], [ 'n1weDdde5xXLfPeutESLaG8swr5jLCqz72', prices['n1weDdde5xXLfPeutESLaG8swr5jLCqz72'] ]]] #body: secret and actual message -> encrypt for destination packet_payloads = [] if (num_packets_freeze == 1): X = randint(1000000000000000000000000000000000000000, 2000000000000000000000000000000000000000) shares = [X] else: X, shares = shamir.make_random_shares(num_packets_freeze, num_packets_freeze) H = sha256(str.encode(str(X))) for i in range(num_packets_freeze): message = secrets.token_urlsafe(packet_size_freeze) secret_share = str(shares[i]) body = {"secret_share": secret_share, "message": message} encrypted_body = encrypt(str.encode(json.dumps(body)), sym_key_dest.sec()) packet_payloads.append(encrypted_body) success = False while success == False: # Find cost of each route and choose cheapest cheap_route_index = find_cheapest_route(routes) cheapest_route = routes[cheap_route_index] # get next hop from route and hence get relevent channel next_hop = get_peer(peers, routes[cheap_route_index][0][0]) next_hop_channel = get_channel(next_hop, channels) cost = route_cost(cheapest_route, num_bytes) commitment_tx = new_commitment_tx(node, next_hop_channel, cost, H) #print(commitment_tx.serialize().hex()) header = { "source": node.address, "route": cheapest_route, "num_packets": num_packets_freeze, "packet_size": packet_size_freeze, "commitment_tx": str(commitment_tx.serialize().hex()) } # send header next_hop.send(str.encode(json.dumps(header))) if (next_hop.receive() == b'header ACK'): for i in range(num_packets_freeze): print(sys.getsizeof(packet_payloads[i])) next_hop.send(packet_payloads[i]) next_hop.receive() reply = json.loads(next_hop.receive().decode()) commitment_tx = Tx.parse( BytesIO(bytes.fromhex(reply['commitment_tx']))) revealed_secret = reply['secret'] if (revealed_secret == X): print( "Successful delivery of message proven. Thus update channel state" ) success = True next_hop_channel.pay(commitment_tx.tx_outs[2].amount) print(get_channel(next_hop, channels)) total_bytes_sent_main += num_bytes total_bytes_sent.set(total_bytes_sent_main) wallet_balance = get_total_channel_balance(channels) local_balance_AB = get_channel_balance(channels[0]) local_balance_AD = get_channel_balance(channels[1]) totalBalance.set(wallet_balance) channel_B_local.set(local_balance_AB) channel_D_local.set(local_balance_AD) print("Total Balance: " + str(wallet_balance)) go = False else: print( "Malicious node detected, choose next cheapest route") routes.pop(cheap_route_index) go = False
def cipher(cls, salt, iv, password): key = password + salt for _ in range(KEY_ITERATIONS): key = sha256(key) return AES.new(key, AES.MODE_CBC, iv)
def sock_checker(node_address): global total_bytes_received_main prev_hop = get_peer(peers, node_address) current_channel = get_channel(prev_hop, channels) sym_key_prev_hop = prev_hop.sym_key while True: received_header = json.loads((prev_hop.receive()).decode()) source = get_peer(peers, received_header['source']) commitment_tx = Tx.parse( BytesIO(bytes.fromhex(received_header['commitment_tx']))) H = check_htlc_and_get_secret_hash(node, commitment_tx, current_channel) num_packets = received_header['num_packets'] packet_size = received_header['packet_size'] num_bytes = num_packets * packet_size #num_kilobytes = int(num_packets*packet_size/1000) prev_hop.send(b'header ACK') #receive body sym_key_source = source.sym_key packet_payloads = [] for i in range(num_packets): packet_payloads.append(prev_hop.receive()) prev_hop.send(b'packet ACK') #decode packets decoded_packets = [] for i in range(len(packet_payloads)): decoded_packets.append( json.loads( decrypt(packet_payloads[i], sym_key_source.sec()).decode())) #get the shares if (num_packets == 1): revealed_secret = int(decoded_packets[0]['secret_share']) else: shares = [] for i in range(len(decoded_packets)): shamir_share = decoded_packets[i]['secret_share'] x, y = map(int, shamir_share.strip('()').split(',')) shares.append((x, y)) revealed_secret = shamir.recover_secret(shares) #check that you can suceesfully unlock the htlc output if (not (H == None) and (sha256(str.encode(str(revealed_secret))) == H)): print("I can sign the htlc output with the secret") #sign the commitment tx commitment_tx.tx_ins[0].script_sig = get_script_sig( commitment_tx, node.private_key) reply = { "commitment_tx": str(commitment_tx.serialize().hex()), "secret": revealed_secret } prev_hop.send(str.encode(json.dumps(reply))) current_channel.paid(commitment_tx.tx_outs[2].amount) print(current_channel) total_bytes_received_main += num_bytes total_bytes_received.set(total_bytes_received_main) wallet_balance = get_total_channel_balance(channels) local_balance_CB = get_channel_balance(channels[0]) local_balance_CD = get_channel_balance(channels[1]) totalBalance.set(wallet_balance) channel_B_local.set(local_balance_CB) channel_D_local.set(local_balance_CD) print("Total Balance: " + str(get_total_channel_balance(channels))) else: print("Cannot unlock HTLC")
def sha256(self): '''Returns the sha256 of the raw serialization for witness program''' return sha256(self.raw_serialize())