def test_proofs(create=False): secp = Secp256k1(None, FLAG_ALL) if create: dct = [] for i in range(100): secret = SecretKey.random(secp) nonce = SecretKey.random(secp) amount = randint(1, 10000000000) proof = secp.bullet_proof(amount, secret, nonce, bytearray()) dct.append({ "secret": secret.to_hex().decode(), "nonce": nonce.to_hex().decode(), "amount": amount, "proof": proof.to_hex().decode() }) f = open("proofs_new.json", "w") f.write(json.dumps(dct, indent=2)) f.close() return f = open("tests/proofs.json", "r") dct = json.loads(f.read()) f.close() test_count = 0 test_equal_count = 0 for test in dct: test_count += 1 secret = SecretKey.from_hex(secp, test['secret'].encode()) nonce = SecretKey.from_hex(secp, test['nonce'].encode()) amount = test['amount'] proof_target = RangeProof.from_hex(test['proof'].encode()) proof = secp.bullet_proof(amount, secret, nonce, bytearray()) commit = secp.commit(amount, secret) assert secp.verify_bullet_proof( commit, proof, bytearray()), "Proof {} fails to verify".format(test_count) if proof == proof_target: test_equal_count += 1 assert test_count == test_equal_count, \ "All proofs verify, but only {} out of {} proofs are the same".format(test_equal_count, test_count)
def receive(self, dct: dict): if self.stage is None: if self.role == Role.BUYER: dct['time_start'] = int(time()) self.wallet = Wallet.open(self.secp, dct['wallet']) # Add 'foreign_' prefix to some keys dct.update({ "foreign_partial_commit": dct['partial_commit'], "foreign_public_nonce": dct['public_nonce'], "foreign_public_refund_nonce": dct['public_refund_nonce'] }) dct.pop("partial_commit", None) dct.pop("public_nonce", None) dct.pop("public_refund_nonce", None) # Partial multisig output self.partial_child, self.partial_entry = self.wallet.create_output( dct['grin_amount']) self.partial_entry.mark_locked() self.nonce = SecretKey.random(self.secp) self.refund_nonce = SecretKey.random(self.secp) self.secret_lock = SecretKey.random(self.secp) self.public_lock = self.secret_lock.to_public_key(self.secp) if dct['swap_currency'] == "BTC": self.btc_lock_time = int(time() + 24 * 60 * 60) self.btc_refund_key = SecretKey.random(self.secp) self.public_btc_refund_key = self.btc_refund_key.to_public_key( self.secp) self.load(dct) if self.is_bitcoin_swap(): self.btc_lock_address = self.calculate_btc_lock_address() self.wallet.save() else: raise Exception("This stage doesn't expect an input file") elif self.stage == Stage.INIT: self.stage = Stage.SIGN self.foreign_t_1 = PublicKey.from_hex(self.secp, dct['t_1'].encode()) self.foreign_t_2 = PublicKey.from_hex(self.secp, dct['t_2'].encode()) if self.role == Role.SELLER: self.foreign_partial_commit = Commitment.from_hex( self.secp, dct['partial_commit'].encode()) self.foreign_public_nonce = PublicKey.from_hex( self.secp, dct['public_nonce'].encode()) self.foreign_public_refund_nonce = PublicKey.from_hex( self.secp, dct['public_refund_nonce'].encode()) self.public_lock = PublicKey.from_hex( self.secp, dct['public_lock'].encode()) if self.is_bitcoin_swap(): self.btc_lock_time = int(dct['btc_lock_time']) self.public_btc_refund_key = PublicKey.from_hex( self.secp, dct['public_btc_refund_key']) self.btc_lock_address = self.calculate_btc_lock_address() if self.is_ether_swap(): self.eth_address_lock = ethereum_address( self.secp, self.public_lock).decode() self.eth_contract_address = dct['eth_contract_address'] self.commit = self.secp.commit_sum([ self.foreign_partial_commit, self.wallet.commit(self.partial_entry) ], []) self.foreign_partial_signature = Signature.from_hex( dct['partial_signature'].encode()) self.foreign_partial_refund_signature = Signature.from_hex( dct['partial_refund_signature'].encode()) else: self.foreign_tau_x = SecretKey.from_hex( self.secp, dct['tau_x'].encode()) elif self.stage == Stage.SIGN: self.stage = Stage.LOCK if self.role == Role.SELLER: self.range_proof = RangeProof.from_hex( dct['range_proof'].encode()) else: self.tx_height = dct['tx_height'] self.foreign_public_swap_nonce = PublicKey.from_hex( self.secp, dct['public_swap_nonce'].encode()) elif self.stage == Stage.LOCK: self.stage = Stage.SWAP if self.role == Role.SELLER: self.foreign_public_swap_nonce = PublicKey.from_hex( self.secp, dct['public_swap_nonce'].encode()) self.swap_fee_amount = int(dct['swap_fee_amount']) self.swap_lock_height = int(dct['swap_lock_height']) self.swap_output = Output.from_dict(self.secp, dct['swap_output'], True) self.swap_offset = BlindingFactor.from_hex( dct['swap_offset'].encode()) self.foreign_partial_swap_adaptor = Signature.from_hex( dct['partial_swap_adaptor']) else: self.foreign_partial_swap_signature = Signature.from_hex( dct['partial_swap_signature']) elif self.stage == Stage.SWAP: self.stage = Stage.DONE if self.role == Role.SELLER: self.foreign_partial_swap_signature = Signature.from_hex( dct['partial_swap_signature']) else: raise Exception("Invalid stage")
def load(self, dct=None): seller = self.role == Role.SELLER buyer = not seller from_file = dct is None if from_file: f = open(absolute(self.swap_file), "r") dct = json.loads(f.read()) f.close() self.stage = Stage(dct['stage']) if self.wallet is None: self.wallet = Wallet.open(self.secp, dct['wallet']) self.time_start = int(dct['time_start']) self.grin_amount = int(dct['grin_amount']) self.swap_currency = dct['swap_currency'] self.swap_amount = int(dct['swap_amount']) if seller or self.is_ether_swap(): self.swap_receive_address = dct['swap_receive_address'] self.lock_height = int(dct['lock_height']) self.refund_lock_height = int(dct['refund_lock_height']) self.inputs = [ Input.from_dict(self.secp, x, True) for x in dct['inputs'] ] self.fee_amount = int(dct['fee_amount']) self.refund_fee_amount = int(dct['refund_fee_amount']) self.change_output = Output.from_dict(self.secp, dct['change_output'], True) if from_file: self.partial_entry = self.wallet.get_output(dct['partial_entry']) self.partial_child = self.wallet.derive_from_entry( self.partial_entry) self.partial_commit = self.wallet.commit_with_child_key( 0, self.partial_child) self.offset = BlindingFactor.from_hex(dct['offset'].encode()) self.refund_output = Output.from_dict(self.secp, dct['refund_output'], True) self.refund_offset = BlindingFactor.from_hex( dct['refund_offset'].encode()) if from_file: self.nonce = SecretKey.from_hex(self.secp, dct['nonce'].encode()) self.refund_nonce = SecretKey.from_hex( self.secp, dct['refund_nonce'].encode()) self.public_nonce = self.nonce.to_public_key(self.secp) self.public_refund_nonce = self.refund_nonce.to_public_key(self.secp) if seller: if self.is_bitcoin_swap(): self.swap_cosign = SecretKey.from_hex( self.secp, dct['swap_cosign'].encode()) self.input_entries = [ self.wallet.get_output(x) for x in dct['input_entries'] ] self.input_amount = sum(x.value for x in self.input_entries) self.change_amount = self.input_amount - self.grin_amount - self.fee_amount self.change_entry = self.wallet.get_output(dct['change_entry']) self.change_child = self.wallet.derive_from_entry( self.change_entry) self.refund_entry = self.wallet.get_output(dct['refund_entry']) self.refund_child = self.wallet.derive_from_entry( self.refund_entry) else: if from_file: self.secret_lock = SecretKey.from_hex( self.secp, dct['secret_lock'].encode()) if self.is_bitcoin_swap(): self.btc_refund_key = SecretKey.from_hex( self.secp, dct['btc_refund_key'].encode()) if self.is_bitcoin_swap(): self.public_swap_cosign = self.swap_cosign.to_public_key(self.secp) if seller else \ PublicKey.from_hex(self.secp, dct['public_swap_cosign'].encode()) if self.stage >= Stage.SIGN or buyer: self.foreign_partial_commit = Commitment.from_hex( self.secp, dct['foreign_partial_commit'].encode()) self.foreign_public_nonce = PublicKey.from_hex( self.secp, dct['foreign_public_nonce'].encode()) self.foreign_public_refund_nonce = PublicKey.from_hex( self.secp, dct['foreign_public_refund_nonce'].encode()) if from_file: self.public_lock = PublicKey.from_hex( self.secp, dct['public_lock'].encode()) if self.is_bitcoin_swap(): self.public_btc_refund_key = self.btc_refund_key.to_public_key(self.secp) if buyer else \ PublicKey.from_hex(self.secp, dct['public_btc_refund_key'].encode()) if self.is_ether_swap(): self.eth_address_lock = ethereum_address( self.secp, self.public_lock).decode() self.commit = self.secp.commit_sum([self.foreign_partial_commit, self.wallet.commit(self.partial_entry)], []) if not from_file else \ Commitment.from_hex(self.secp, dct['commit'].encode()) if self.stage >= Stage.SIGN or (buyer and from_file): self.public_excess = PublicKey.from_hex( self.secp, dct['public_excess'].encode()) self.public_refund_excess = PublicKey.from_hex( self.secp, dct['public_refund_excess'].encode()) if self.is_bitcoin_swap(): self.btc_lock_time = int(dct['btc_lock_time']) self.btc_lock_address = Address.from_base58check( dct['btc_lock_address'].encode()) if self.is_ether_swap(): self.eth_contract_address = dct['eth_contract_address'] self.partial_signature = Signature.from_hex( dct['partial_signature'].encode()) self.partial_refund_signature = Signature.from_hex( dct['partial_refund_signature'].encode()) self.t_1 = PublicKey.from_hex(self.secp, dct['t_1'].encode()) self.t_2 = PublicKey.from_hex(self.secp, dct['t_2'].encode()) if self.stage >= Stage.SIGN: self.foreign_t_1 = PublicKey.from_hex(self.secp, dct['foreign_t_1'].encode()) self.foreign_t_2 = PublicKey.from_hex(self.secp, dct['foreign_t_2'].encode()) if seller: self.tau_x = SecretKey.from_hex(self.secp, dct['tau_x'].encode()) self.foreign_partial_signature = Signature.from_hex( dct['foreign_partial_signature'].encode()) self.foreign_partial_refund_signature = Signature.from_hex( dct['foreign_partial_refund_signature'].encode()) if self.is_bitcoin_swap(): self.btc_output_points = [ OutputPoint.from_hex(x.encode()) for x in dct['btc_output_points'] ] else: self.foreign_tau_x = SecretKey.from_hex( self.secp, dct['foreign_tau_x'].encode()) if self.stage >= Stage.LOCK or (self.stage == Stage.SIGN and buyer): self.range_proof = RangeProof.from_hex(dct['range_proof'].encode()) if self.stage >= Stage.LOCK: self.tx_height = dct['tx_height'] self.swap_nonce = SecretKey.from_hex(self.secp, dct['swap_nonce'].encode()) self.public_swap_nonce = self.swap_nonce.to_public_key(self.secp) if buyer: self.swap_entry = self.wallet.get_output(dct['swap_entry']) self.swap_child = self.wallet.derive_from_entry( self.swap_entry) self.partial_swap_adaptor = Signature.from_hex( dct['partial_swap_adaptor'].encode()) if (buyer and self.stage >= Stage.LOCK) or (seller and self.stage >= Stage.SWAP): self.foreign_public_swap_nonce = PublicKey.from_hex( self.secp, dct['foreign_public_swap_nonce'].encode()) self.swap_fee_amount = int(dct['swap_fee_amount']) self.swap_lock_height = int(dct['swap_lock_height']) self.swap_output = Output.from_dict(self.secp, dct['swap_output'], True) self.swap_offset = BlindingFactor.from_hex( dct['swap_offset'].encode()) self.public_swap_excess = PublicKey.from_hex( self.secp, dct['public_swap_excess'].encode()) self.partial_swap_signature = Signature.from_hex( dct['partial_swap_signature'].encode()) if seller and self.stage >= Stage.SWAP: self.foreign_partial_swap_adaptor = Signature.from_hex( dct['foreign_partial_swap_adaptor'].encode())