Пример #1
0
 def EncodeInt_CheckDecode(self, value, numberOfBytes):
     result = TransactionEncoding._encodeInt(value, numberOfBytes)
     self.assertTrue(type(result) is type(b''))
     self.assertEqual(len(result), numberOfBytes)
     decoded = TransactionEncoding._decodeInt(result)
     self.assertEqual(decoded, value)
     return result
Пример #2
0
 def test_destination_range(self):
     details = {
         'pendingExchangeIndex': 32,
         'destinationAddress': 'destinationPKH',
         'destinationAmount': 100
     }
     tx = TransactionEncoding.FromStateTransaction('LTCExchangeCompletion',
                                                   None, (), (), details)
     details['destinationAmount'] = 0
     tx = TransactionEncoding.FromStateTransaction('LTCExchangeCompletion',
                                                   None, (), (), details)
     details['destinationAmount'] = -1
     self.assertRaisesRegexp(ExceptionReportedToUser,
                             'Negative output amounts are not permitted',
                             TransactionEncoding.FromStateTransaction,
                             'LTCExchangeCompletion', None, (), (), details)
     details['destinationAmount'] = 0xffffffffffffffff
     tx = TransactionEncoding.FromStateTransaction('LTCExchangeCompletion',
                                                   None, (), (), details)
     details['destinationAmount'] += 1
     self.assertRaisesRegexp(
         ExceptionReportedToUser,
         'Control address output amount exceeds supported range',
         TransactionEncoding.FromStateTransaction, 'LTCExchangeCompletion',
         None, (), (), details)
Пример #3
0
 def test_forwarding(self):
     # cannot encode forward to future network version transactions explicitly from state transactions
     self.assertRaisesRegexp(
         Exception,
         "('Unknown transaction type string', 'ForwardToFutureNetworkVersion')",
         TransactionEncoding.FromStateTransaction,
         'ForwardToFutureNetworkVersion', [('sourceTXID', 4)], ('change', ),
         ('changePKH', ), {
             'amount': 999,
             'maxBlock': 100
         })
     # pay transactions satisfy format requirements for forward to future network transactions
     # so hack the type code for a pay transaction to test this
     tx = TransactionEncoding.FromStateTransaction(
         'Pay', [('sourceTXID', 4)], ('change', 'destination'),
         ('changePKH', 'destinationPKH'), {
             'amount': 20,
             'maxBlock': 100
         })
     tx._outputs[0] = (
         b'SB\x0f\x14\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         0)
     transactionType, sourceAccounts, outputs, details = TransactionEncoding.ToStateTransaction(
         tx)
     self.assertEqual(transactionType, 'ForwardToFutureNetworkVersion')
     self.assertEqual(sourceAccounts, [('sourceTXID', 4)])
     self.assertEqual(outputs, ('change', ))
     self.assertDictEqual(details, {'amount': 20, 'maxBlock': 100})
     # same as above, but with max typecode interpreted in this way
     tx._outputs[0] = (
         b'SB\x7f\x14\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         1)
     transactionType, sourceAccounts, outputs, details = TransactionEncoding.ToStateTransaction(
         tx)
     self.assertEqual(transactionType, 'ForwardToFutureNetworkVersion')
     self.assertEqual(sourceAccounts, [('sourceTXID', 4)])
     self.assertEqual(outputs, ('change', ))
     self.assertDictEqual(details, {'amount': 20, 'maxBlock': 100})
     # after that, we get unfunded transactions
     tx._outputs[0] = (
         b'SB\x80\x14\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         0)
     transactionType, sourceAccounts, outputs, details = TransactionEncoding.ToStateTransaction(
         tx)
     self.assertEqual(transactionType, 'LTCExchangeCompletion')
     # codes after unfunded not supported (increase the typecode byte, if more unfunded added)
     tx._outputs[0] = (
         b'SB\x90\x14\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         0)
     self.assertRaises(TransactionEncoding.UnsupportedTransaction,
                       TransactionEncoding.ToStateTransaction, tx)
     # and ditto up to end of typecode byte range
     tx._outputs[0] = (
         b'SB\xff\x14\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         0)
     self.assertRaises(TransactionEncoding.UnsupportedTransaction,
                       TransactionEncoding.ToStateTransaction, tx)
Пример #4
0
 def test_bad_state_transactions(self):
     # outputs don't match spec
     self.assertRaises(AssertionError,
                       TransactionEncoding.FromStateTransaction, 'Burn', [],
                       (), (), {'amount': 10})
     # outputs don't match spec
     self.assertRaises(AssertionError,
                       TransactionEncoding.FromStateTransaction, 'Burn', [],
                       ('dostination', ), ('_pkh', ), {'amount': 10})
     # Burn is a funded type, so must have sourceAccounts list set
     self.assertRaises(AssertionError,
                       TransactionEncoding.FromStateTransaction, 'Burn',
                       None, ('destination', ), ('_pkh', ), {'amount': 10})
     # bad type string
     self.assertRaisesRegexp(
         Exception, "('Unknown transaction type string', 'Burneeyo')",
         TransactionEncoding.FromStateTransaction, 'Burneeyo', [],
         ('destination', ), ('_pkh', ), {'amount': 10})
     # lengths of keys and outputs spec don't match
     self.assertRaises(AssertionError,
                       TransactionEncoding.FromStateTransaction, 'Pay',
                       [('sourceTXID', 4)], ('change', 'destination'),
                       ('changePKH'), {
                           'amount': 20,
                           'maxBlock': 100
                       })
     # LTCExchangeCompletion is unfunded, so must not have sourceAccounts list set
     self.assertRaises(
         AssertionError, TransactionEncoding.FromStateTransaction,
         'LTCExchangeCompletion', [], (), (), {
             'pendingExchangeIndex': 10,
             'destinationAddress': 'madeUpAddress',
             'destinationAmount': 10
         })
     # control group!
     TransactionEncoding.FromStateTransaction('Burn', [], ('destination', ),
                                              ('_pkh', ), {'amount': 10})
     TransactionEncoding.FromStateTransaction(
         'Pay', [('sourceTXID', 4)], ('change', 'destination'),
         ('changePKH', 'destinationPKH'), {
             'amount': 20,
             'maxBlock': 100
         })
     TransactionEncoding.FromStateTransaction(
         'LTCExchangeCompletion', None, (), (), {
             'pendingExchangeIndex': 10,
             'destinationAddress': 'madeUpAddress',
             'destinationAmount': 10
         })
Пример #5
0
 def CheckAndSend_Funded(transactionType, outputs, outputPubKeys, details):
     TransactionEncoding.FromStateTransaction(
         transactionType, [], outputs, outputPubKeys,
         details)  # for initial parameter checking
     transactionBuildLayer.startTransactionConstruction()
     swapBillUnspent = transactionBuildLayer.getSwapBillUnspent(state)
     sourceAccounts = []
     while True:
         try:
             state.checkTransaction(transactionType,
                                    outputs=outputs,
                                    transactionDetails=details,
                                    sourceAccounts=sourceAccounts)
         except InsufficientFundsForTransaction:
             pass
         except TransactionFailsAgainstCurrentState as e:
             raise TransactionNotSuccessfulAgainstCurrentState(
                 'Transaction would not complete successfully against current state: '
                 + str(e))
         except BadlyFormedTransaction as e:
             raise ExceptionReportedToUser(
                 'Transaction does not meet protocol constraints: ' +
                 str(e))
         else:
             break
         if not swapBillUnspent:
             raise ExceptionReportedToUser(
                 'Insufficient swapbill for transaction.')
         transactionBuildLayer.swapBillUnspentUsed(swapBillUnspent[0])
         sourceAccounts.append(swapBillUnspent[0])
         swapBillUnspent = swapBillUnspent[1:]
     return CheckAndSend_Common(transactionType, sourceAccounts, outputs,
                                outputPubKeys, details)
Пример #6
0
 def checkIgnoredBytes(self, tx, numberOfIgnoredBytes):
     transactionType, sourceAccounts, outputs, details = TransactionEncoding.ToStateTransaction(
         tx)
     for fillByte in (b'\xff', b'\x00', b'\x80'):
         if numberOfIgnoredBytes > 0:
             tx._outputs[0] = (tx._outputs[0][0][:-numberOfIgnoredBytes] +
                               fillByte * numberOfIgnoredBytes,
                               tx._outputs[0][1])
             transactionType_Check, sourceAccounts_Check, outputs_Check, details_Check = TransactionEncoding.ToStateTransaction(
                 tx)
             self.assertEqual(transactionType, transactionType_Check)
             self.assertEqual(sourceAccounts, sourceAccounts_Check)
             self.assertEqual(outputs, outputs_Check)
             self.assertDictEqual(details, details_Check)
     try:
         for fillByte in (b'\xff', b'\x00', b'\x80'):
             tx._outputs[0] = (
                 tx._outputs[0][0][:-(numberOfIgnoredBytes + 1)] +
                 fillByte * (numberOfIgnoredBytes + 1), tx._outputs[0][1])
             transactionType_Check, sourceAccounts_Check, outputs_Check, details_Check = TransactionEncoding.ToStateTransaction(
                 tx)
             self.assertEqual(transactionType, transactionType_Check)
             self.assertEqual(sourceAccounts, sourceAccounts_Check)
             self.assertEqual(outputs, outputs_Check)
             self.assertDictEqual(details, details_Check)
     except (TransactionEncoding.NotValidSwapBillTransaction,
             AssertionError):
         pass
     else:
         raise Exception(
             'Expected decoding failure with extra byte overwrite!')
Пример #7
0
 def Wrapper(transactionType, sourceAccounts, outputs, outputPubKeyHashes,
             originalDetails):
     tx = originalFunction(transactionType, sourceAccounts, outputs,
                           outputPubKeyHashes, originalDetails)
     transactionType_Check, sourceAccounts_Check, outputs_Check, details_Check = TransactionEncoding.ToStateTransaction(
         tx)
     assert transactionType_Check == transactionType
     assert sourceAccounts_Check == sourceAccounts
     assert outputs_Check == outputs
     assert details_Check == originalDetails
     return tx
Пример #8
0
 def CheckAndSend_Common(transactionType, sourceAccounts, outputs,
                         outputPubKeys, details):
     change = host.getNewNonSwapBillAddress()
     print('attempting to send ' + FormatTransactionForUserDisplay.Format(
         host, transactionType, outputs, outputPubKeys, details),
           file=out)
     baseTX = TransactionEncoding.FromStateTransaction(
         transactionType, sourceAccounts, outputs, outputPubKeys, details)
     backingUnspent = transactionBuildLayer.getUnspent()
     baseInputsAmount = 0
     for i in range(baseTX.numberOfInputs()):
         txID = baseTX.inputTXID(i)
         vOut = baseTX.inputVOut(i)
         baseInputsAmount += ownedAccounts.accounts[(txID, vOut)][0]
     txID = SetFeeAndSend(baseTX, baseInputsAmount, backingUnspent)
     return {'transaction id': txID}
Пример #9
0
 def CheckAndSend_UnFunded(transactionType, outputs, outputPubKeys,
                           details):
     TransactionEncoding.FromStateTransaction(
         transactionType, None, outputs, outputPubKeys,
         details)  # for initial parameter checking
     transactionBuildLayer.startTransactionConstruction()
     try:
         state.checkTransaction(transactionType,
                                outputs=outputs,
                                transactionDetails=details,
                                sourceAccounts=None)
     except TransactionFailsAgainstCurrentState as e:
         raise TransactionNotSuccessfulAgainstCurrentState(
             'Transaction would not complete successfully against current state: '
             + str(e))
     except BadlyFormedTransaction as e:
         raise ExceptionReportedToUser(
             'Transaction does not follow protocol rules: ' + str(e))
     return CheckAndSend_Common(transactionType, None, outputs,
                                outputPubKeys, details)
Пример #10
0
def _processTransactions(state, wallet, ownedAccounts, transactions,
                         applyToState, reportPrefix, out):
    for txID, hostTXBytes in transactions:
        hostTX, scriptPubKeys = RawTransaction.Decode(hostTXBytes)
        if RawTransaction.UnexpectedFormat_Fast(hostTXBytes,
                                                ControlAddressPrefix.prefix):
            continue
        inputsReport = ownedAccounts.updateForSpent(hostTX, state)
        try:
            transactionType, sourceAccounts, outputs, transactionDetails = TransactionEncoding.ToStateTransaction(
                hostTX)
            appliedSuccessfully = True
        except (TransactionEncoding.NotValidSwapBillTransaction,
                TransactionEncoding.UnsupportedTransaction):
            if inputsReport != '':
                print(reportPrefix + ': <invalid transaction>', file=out)
                print(inputsReport, end="", file=out)
            continue
        if inputsReport != '':
            print(reportPrefix + ': ' + transactionType, file=out)
            print(inputsReport, end="", file=out)
        if not applyToState:
            continue
        #inBetweenReport = ownedAccounts.checkForTradeOfferChanges(state)
        #assert inBetweenReport == ''
        error = state.applyTransaction(transactionType,
                                       txID,
                                       sourceAccounts=sourceAccounts,
                                       transactionDetails=transactionDetails,
                                       outputs=outputs)
        outputsReport = ownedAccounts.checkForTradeOfferChanges(state)
        outputsReport += ownedAccounts.updateForNewOutputs(
            wallet, state, txID, hostTX, outputs, scriptPubKeys)
        if outputsReport:
            if inputsReport == '':
                # didn't print this line yet
                print(reportPrefix + ': ' + transactionType, file=out)
            print(outputsReport, end="", file=out)
        if (outputsReport or inputsReport) and error is not None:
            print(' * failed:', error, file=out)
Пример #11
0
 def test_bad_burn_address(self):
     tx = TransactionEncoding.FromStateTransaction('Burn', [],
                                                   ('destination', ),
                                                   ('_pkh', ),
                                                   {'amount': 10})
     self.assertEqual(tx._outputs[0], (
         b'SB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         10))
     tx._outputs[0] = (
         b'SB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01',
         10)
     self.assertRaises(TransactionEncoding.NotValidSwapBillTransaction,
                       TransactionEncoding.ToStateTransaction, tx)
     tx._outputs[0] = (
         b'SB\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         10)
     self.assertRaises(TransactionEncoding.NotValidSwapBillTransaction,
                       TransactionEncoding.ToStateTransaction, tx)
     tx._outputs[0] = (
         b'SB\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
         10)
     self.assertRaises(TransactionEncoding.NotValidSwapBillTransaction,
                       TransactionEncoding.ToStateTransaction, tx)
Пример #12
0
 def test_types(self):
     tx = TransactionEncoding.FromStateTransaction('Burn', [],
                                                   ('destination', ),
                                                   ('_pkh', ),
                                                   {'amount': 10})
     self.assertDictEqual(
         tx.__dict__, {
             '_inputs': [],
             '_outputs':
             [(b'SB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
               10), ('_pkh', 0)]
         })
     tx = TransactionEncoding.FromStateTransaction(
         'Pay', [('sourceTXID', 4)], ('change', 'destination'),
         ('changePKH', 'destinationPKH'), {
             'amount': 20,
             'maxBlock': 100
         })
     self.assertDictEqual(
         tx.__dict__, {
             '_inputs': [('sourceTXID', 4)],
             '_outputs':
             [(b'SB\x01\x14\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
               0), ('changePKH', 0), ('destinationPKH', 0)]
         })
     self.checkIgnoredBytes(tx, 7)
     tx = TransactionEncoding.FromStateTransaction(
         'LTCBuyOffer', [('sourceTXID', 5)], ('ltcBuy', ), ('ltcBuyPKH', ),
         {
             'receivingAddress': 'ltcReceivePKH',
             'swapBillOffered': 22,
             'maxBlock': 0,
             'exchangeRate': 123
         })
     self.assertDictEqual(
         tx.__dict__, {
             '_outputs':
             [(b'SB\x02\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00{\x00\x00\x00\x00\x00\x00',
               0), ('ltcBuyPKH', 0), ('ltcReceivePKH', 0)],
             '_inputs': [('sourceTXID', 5)]
         })
     self.checkIgnoredBytes(tx, 3)
     tx = TransactionEncoding.FromStateTransaction('LTCSellOffer',
                                                   [('sourceTXID', 3)],
                                                   ('ltcSell', ),
                                                   ('ltcSellPKH', ), {
                                                       'ltcOffered': 22,
                                                       'maxBlock': 0,
                                                       'exchangeRate': 123
                                                   })
     self.assertDictEqual(
         tx.__dict__, {
             '_inputs': [('sourceTXID', 3)],
             '_outputs':
             [(b'SB\x03\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00{\x00\x00\x00\x00\x00\x00',
               0), ('ltcSellPKH', 0)]
         })
     self.checkIgnoredBytes(tx, 3)
     tx = TransactionEncoding.FromStateTransaction(
         'LTCExchangeCompletion', None, (), (), {
             'pendingExchangeIndex': 32,
             'destinationAddress': 'destinationPKH',
             'destinationAmount': 999
         })
     self.assertDictEqual(
         tx.__dict__, {
             '_inputs': [],
             '_outputs':
             [(b'SB\x80 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
               0), ('destinationPKH', 999)]
         })
     self.checkIgnoredBytes(tx, 11)
     tx = TransactionEncoding.FromStateTransaction(
         'BackLTCSells', [('sourceTXID', 7)], ('ltcSellBacker', ),
         ('ltcSellBackerPKH', ), {
             'backingAmount': 32,
             'transactionsBacked': 4,
             'ltcReceiveAddress': 'receivePKH',
             'maxBlock': 123,
             'commission': 0xfffffff
         })
     self.assertDictEqual(
         tx.__dict__, {
             '_inputs': [('sourceTXID', 7)],
             '_outputs':
             [(b'SB\x04 \x00\x00\x00\x00\x00\x04\x00\x00{\x00\x00\x00\xff\xff\xff\x0f',
               0), ('ltcSellBackerPKH', 0), ('receivePKH', 0)]
         })
     self.checkIgnoredBytes(tx, 0)