Improves carrier

- Takes receipt out of Carrier
- Adds missing cases (implementation missing)
- Adds notes on what to check
This commit is contained in:
Sergi Delgado Segura
2019-10-10 12:34:18 +01:00
parent db635ef688
commit eb2734ccfe

View File

@@ -4,19 +4,20 @@ from pisa.utils.auth_proxy import JSONRPCException
from pisa.errors import UNKNOWN_JSON_RPC_EXCEPTION
class Carrier:
class Receipt:
def __init__(self, delivered, confirmations=0, reason=None):
self.delivered = delivered
self.confirmations = confirmations
self.reason = reason
class Receipt:
def __init__(self, delivered, confirmations=0, reason=None):
self.delivered = delivered
self.confirmations = confirmations
self.reason = reason
class Carrier:
def send_transaction(self, rawtx, txid):
try:
logging.info("[Carrier] pushing transaction to the network (txid: {})".format(rawtx))
bitcoin_cli.sendrawtransaction(rawtx)
receipt = self.Receipt(delivered=True)
receipt = Receipt(delivered=True)
except JSONRPCException as e:
errno = e.error.get('code')
@@ -26,10 +27,18 @@ class Carrier:
if errno == RPC_VERIFY_REJECTED:
# DISCUSS: what to do in this case
# DISCUSS: invalid transactions (properly formatted but invalid, like unsigned) fit here too.
# DISCUSS: RPC_VERIFY_ERROR could also be a possible case.
# DISCUSS: check errors -9 and -10
# TODO: UNKNOWN_JSON_RPC_EXCEPTION is not the proper exception here. This is long due.
receipt = self.Receipt(delivered=False, reason=UNKNOWN_JSON_RPC_EXCEPTION)
receipt = Receipt(delivered=False, reason=UNKNOWN_JSON_RPC_EXCEPTION)
elif errno == RPC_VERIFY_ERROR:
# DISCUSS: The only reason for it seems to bea non-existing or spent input.
# https://github.com/bitcoin/bitcoin/blob/master/src/rpc/rawtransaction.cpp#L660
# However RPC_TRANSACTION_ERROR aliases RPC_VERIFY_ERROR and it's the default return for
# RPCErrorFromTransactionError
# https://github.com/bitcoin/bitcoin/blob/master/src/rpc/util.cpp#L276
# TODO: UNKNOWN_JSON_RPC_EXCEPTION is not the proper exception here. This is long due.
receipt = Receipt(delivered=False, reason=UNKNOWN_JSON_RPC_EXCEPTION)
elif errno == RPC_VERIFY_ALREADY_IN_CHAIN:
logging.info("[Carrier] {} is already in the blockchain. Getting confirmation count".format(txid))
@@ -40,28 +49,34 @@ class Carrier:
if tx_info is not None:
confirmations = int(tx_info.get("confirmations"))
receipt = self.Receipt(delivered=True, confirmations=confirmations)
receipt = Receipt(delivered=True, confirmations=confirmations, reason=RPC_VERIFY_ALREADY_IN_CHAIN)
else:
# There's a really unlike edge case where a transaction can be reorged between receiving the
# notification and querying the data. In such a case we just resend
self.send_transaction(rawtx, txid)
elif errno == RPC_DESERIALIZATION_ERROR:
# Adding this here just for completeness. We should never end up here. The Carrier only sends txs
# handed by the Responder, who receives them from the Watcher, who checks that the tx can be properly
# deserialized
logging.info("[Carrier] tx {} cannot be deserialized".format(txid))
receipt = Receipt(delivered=False, reason=RPC_DESERIALIZATION_ERROR)
else:
# If something else happens (unlikely but possible) log it so we can treat it in future releases
logging.error("[Responder] JSONRPCException. Error {}".format(e))
receipt = self.Receipt(delivered=False, reason=UNKNOWN_JSON_RPC_EXCEPTION)
receipt = Receipt(delivered=False, reason=UNKNOWN_JSON_RPC_EXCEPTION)
return receipt
@staticmethod
def get_transaction(txid):
tx_info = None
try:
tx_info = bitcoin_cli.getrawtransaction(txid, 1)
except JSONRPCException as e:
tx_info = None
# While it's quite unlikely, the transaction that was already in the blockchain could have been
# reorged while we were querying bitcoind to get the confirmation count. In such a case we just
# restart the job