Skip to content

Commit

Permalink
Merge pull request #30 from AdamISZ/fees
Browse files Browse the repository at this point in the history
Fees implementation as per #8
  • Loading branch information
AdamISZ authored Jun 2, 2017
2 parents 0689d4a + a36721e commit cd39b5c
Show file tree
Hide file tree
Showing 9 changed files with 745 additions and 159 deletions.
2 changes: 1 addition & 1 deletion coinswap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
get_coinswap_secret, get_current_blockheight,
create_hash_script, get_secret_from_vin,
generate_escrow_redeem_script, get_transactions_from_block,
StateMachine, prepare_ecdsa_msg)
StateMachine, prepare_ecdsa_msg, FeePolicy)
from .configure import (cs_single, get_log, load_coinswap_config)
from .cli_options import get_coinswap_parser
from .blockchaininterface import (sync_wallet, RegtestBitcoinCoreInterface,
Expand Down
74 changes: 52 additions & 22 deletions coinswap/alice.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ def handshake(self):
"tx01_confirm_wait"),
"source_chain": "BTC",
"destination_chain": "BTC",
"amount": self.coinswap_parameters.tx0_amount}
"amount": self.coinswap_parameters.base_amount,
"bitcoin_fee": self.coinswap_parameters.bitcoin_fee}
self.send(to_send)
return (True, "Handshake OK")

Expand All @@ -134,16 +135,13 @@ def negotiate_coinswap_parameters(self, carol_response):
if not len(carol_response[0]) == 32:
return (False, "Error: server returned invalid session ID")
self.coinswap_parameters.set_session_id(carol_response[0])
to_send = [self.coinswap_parameters.tx0_amount,
self.coinswap_parameters.tx2_recipient_amount,
self.coinswap_parameters.tx3_recipient_amount,
self.keyset["key_2_2_AC_0"][1],
to_send = [self.keyset["key_2_2_AC_0"][1],
self.keyset["key_2_2_CB_1"][1],
self.keyset["key_TX2_lock"][1],
self.keyset["key_TX3_secret"][1],
self.coinswap_parameters.timeouts["LOCK0"],
self.coinswap_parameters.timeouts["LOCK1"],
self.coinswap_parameters.tx5_address]
self.coinswap_parameters.output_addresses["tx5_address"]]
self.send(*to_send)
return (True, "Coinswap parameters sent OK")

Expand All @@ -162,7 +160,33 @@ def complete_negotiation(self, carol_response):
self.coinswap_parameters.set_pubkey("key_2_2_CB_0", carol_response[0][2])
self.coinswap_parameters.set_pubkey("key_TX2_secret", carol_response[0][3])
self.coinswap_parameters.set_pubkey("key_TX3_lock", carol_response[0][4])
self.coinswap_parameters.set_tx4_address(carol_response[0][5])
proposed_fee = carol_response[0][6]
if self.fee_checker:
if not self.fee_checker(proposed_fee):
return (False, "Server's proposed fee: " + str(proposed_fee) + \
" is not accepted.")
else:
cslog.info("Server proposed fee: " + str(proposed_fee) + \
", accepted.")
self.coinswap_parameters.set_coinswap_fee(carol_response[0][6])
proposed_blinding_amount = carol_response[0][7]
#Is this blinding factor good enough according to our wishes?
if proposed_blinding_amount < cs_single().config.getint("POLICY",
"minimum_blinding_amount"):
return (False, "Blinding amount is too small for us: " + \
str(proposed_blinding_amount) + "but we require at least: " + \
str(cs_single().config.getint("POLICY", "minimum_blinding_amount")))
self.coinswap_parameters.set_blinding_amount(proposed_blinding_amount)
self.coinswap_parameters.set_addr_data(addr4=carol_response[0][5],
addr_2_carol=carol_response[0][8],
addr_3_carol=carol_response[0][9],
addr_5_carol=carol_response[0][10])
proposed_sessionid = carol_response[0][11]
if not len(proposed_sessionid) == 32:
return (False, "Invalid sessionid proposal: " + str(proposed_sessionid))
self.coinswap_parameters.set_session_id(proposed_sessionid)
#The state file name setting had to be deferred until here:
self.state_file = self.state_file + proposed_sessionid + ".json"
if not self.coinswap_parameters.is_complete():
return (False,
"Coinswap public parameter negotiation failed, incomplete.")
Expand All @@ -188,11 +212,8 @@ def send_tx0id_hx_tx2sig(self):
signing_pubkeys = [[btc.privkey_to_pubkey(x)] for x in self.signing_privkeys]
signing_redeemscripts = [btc.address_to_script(
x['address']) for x in self.initial_utxo_inputs.values()]
#calculate size of change output; default p2pkh assumed
fee = estimate_tx_fee(len(self.initial_utxo_inputs), 2)
cslog.debug("got tx0 fee: " + str(fee))
cslog.debug("for tx0 input amount: " + str(total_in))
change_amount = total_in - self.coinswap_parameters.tx0_amount - fee
change_amount = total_in - self.coinswap_parameters.tx0_amount - \
self.coinswap_parameters.bitcoin_fee
cslog.debug("got tx0 change amount: " + str(change_amount))
#get a change address in same mixdepth
change_address = self.wallet.get_internal_addr(0)
Expand All @@ -218,10 +239,12 @@ def send_tx0id_hx_tx2sig(self):
self.coinswap_parameters.pubkeys["key_2_2_AC_1"],
self.coinswap_parameters.pubkeys["key_TX2_secret"],
utxo_in=utxo_in,
recipient_amount=self.coinswap_parameters.tx2_recipient_amount,
recipient_amount=self.coinswap_parameters.tx2_amounts["script"],
hashed_secret=self.hashed_secret,
absolutelocktime=self.coinswap_parameters.timeouts["LOCK0"],
refund_pubkey=self.coinswap_parameters.pubkeys["key_TX2_lock"])
refund_pubkey=self.coinswap_parameters.pubkeys["key_TX2_lock"],
carol_only_address=self.coinswap_parameters.output_addresses["tx2_carol_address"],
carol_only_amount=self.coinswap_parameters.tx2_amounts["carol"])
#Create our own signature for TX2
self.tx2.sign_at_index(self.keyset["key_2_2_AC_0"][0], 0)
sigtx2 = self.tx2.signatures[0][0]
Expand Down Expand Up @@ -255,10 +278,13 @@ def receive_txid1_tx23sig(self, params):
self.coinswap_parameters.pubkeys["key_2_2_CB_1"],
self.coinswap_parameters.pubkeys["key_TX3_secret"],
utxo_in=self.txid1,
recipient_amount=self.coinswap_parameters.tx3_recipient_amount,
recipient_amount=self.coinswap_parameters.tx3_amounts["script"],
hashed_secret=self.hashed_secret,
absolutelocktime=self.coinswap_parameters.timeouts["LOCK1"],
refund_pubkey=self.coinswap_parameters.pubkeys["key_TX3_lock"])
refund_pubkey=self.coinswap_parameters.pubkeys["key_TX3_lock"],
carol_only_address=self.coinswap_parameters.output_addresses["tx3_carol_address"],
carol_only_amount=self.coinswap_parameters.tx3_amounts["carol"])
cslog.info("Alice is working with this TX3: " + str(self.tx3))
if not self.tx3.include_signature(0, sigtx3):
return (False, "Counterparty signature for TX3 invalid.")
#TX3 must be watched for updates
Expand Down Expand Up @@ -332,8 +358,10 @@ def receive_tx5_sig(self, sigmsg):
self.coinswap_parameters.pubkeys["key_2_2_CB_0"],
self.coinswap_parameters.pubkeys["key_2_2_CB_1"],
utxo_in=self.txid1,
destination_address=self.coinswap_parameters.tx5_address,
destination_amount=self.coinswap_parameters.tx5_amount)
destination_address=self.coinswap_parameters.output_addresses["tx5_address"],
destination_amount=self.coinswap_parameters.tx5_amounts["alice"],
carol_change_address=self.coinswap_parameters.output_addresses["tx5_carol_address"],
carol_change_amount=self.coinswap_parameters.tx5_amounts["carol"])
if not self.tx5.include_signature(0, sig):
return (False, "Counterparty signature for TX5 not valid; backing out.")
return (True, "Counterparty signature for TX5 OK.")
Expand Down Expand Up @@ -370,8 +398,10 @@ def send_tx4_sig(self):
self.tx4 = CoinSwapTX45.from_params(self.coinswap_parameters.pubkeys["key_2_2_AC_0"],
self.coinswap_parameters.pubkeys["key_2_2_AC_1"],
utxo_in=utxo_in,
destination_address=self.coinswap_parameters.tx4_address,
destination_amount=self.coinswap_parameters.tx4_amount)
destination_address=self.coinswap_parameters.output_addresses["tx4_address"],
destination_amount=self.coinswap_parameters.tx4_amounts["carol"],
carol_change_address=None,
carol_change_amount=None)
self.tx4.sign_at_index(self.keyset["key_2_2_AC_0"][0], 0)
sig = self.tx4.signatures[0][0]
self.send(sig, self.tx5.txid)
Expand Down Expand Up @@ -422,10 +452,10 @@ def check_server_status(self, status):
elif status["busy"] or status["maximum_amount"] < 0:
cslog.info("Server is not currently available")
reactor.stop()
elif self.coinswap_parameters.tx0_amount < status["minimum_amount"]:
elif self.coinswap_parameters.base_amount < status["minimum_amount"]:
cslog.info("Amount too small for server")
reactor.stop()
elif self.coinswap_parameters.tx0_amount > status["maximum_amount"]:
elif self.coinswap_parameters.base_amount > status["maximum_amount"]:
cslog.info("Amount too large for server")
reactor.stop()
else:
Expand Down
Loading

0 comments on commit cd39b5c

Please sign in to comment.