def test_from_nonstd_scriptPubKey(self): """CRavencoinAddress.from_scriptPubKey() with non-standard scriptPubKeys""" # Bad P2SH scriptPubKeys # non-canonical pushdata scriptPubKey = CScript(x('a94c14000000000000000000000000000000000000000087')) with self.assertRaises(CRavencoinAddressError): CRavencoinAddress.from_scriptPubKey(scriptPubKey) # Bad P2PKH scriptPubKeys # Missing a byte scriptPubKey = CScript(x('76a914000000000000000000000000000000000000000088')) with self.assertRaises(CRavencoinAddressError): CRavencoinAddress.from_scriptPubKey(scriptPubKey) # One extra byte scriptPubKey = CScript(x('76a914000000000000000000000000000000000000000088acac')) with self.assertRaises(CRavencoinAddressError): CRavencoinAddress.from_scriptPubKey(scriptPubKey) # One byte changed scriptPubKey = CScript(x('76a914000000000000000000000000000000000000000088ad')) with self.assertRaises(CRavencoinAddressError): CRavencoinAddress.from_scriptPubKey(scriptPubKey)
def test_bloom_create_insert_key(self): filter = CBloomFilter(2, 0.001, 0, CBloomFilter.UPDATE_ALL) pubkey = x( '045B81F0017E2091E2EDCD5EECF10D5BDD120A5514CB3EE65B8447EC18BFC4575C6D5BF415E54E03B1067934A0F0BA76B01C6B9AB227142EE1D543764B69D901E0' ) pubkeyhash = ravencoin.core.Hash160(pubkey) filter.insert(pubkey) filter.insert(pubkeyhash) self.assertEqual(filter.serialize(), x('038fc16b080000000000000001'))
def test_from_invalid_scriptPubKey(self): """CRavencoinAddress.from_scriptPubKey() with invalid scriptPubKeys""" # We should raise a CRavencoinAddressError, not any other type of error # Truncated P2SH scriptPubKey = CScript(x('a91400000000000000000000000000000000000000')) with self.assertRaises(CRavencoinAddressError): CRavencoinAddress.from_scriptPubKey(scriptPubKey) # Truncated P2PKH scriptPubKey = CScript(x('76a91400000000000000000000000000000000000000')) with self.assertRaises(CRavencoinAddressError): CRavencoinAddress.from_scriptPubKey(scriptPubKey)
def test_from_valid_pubkey(self): """Create P2PKHRavencoinAddress's from valid pubkeys""" def T(pubkey, expected_str_addr): addr = P2PKHRavencoinAddress.from_pubkey(pubkey) self.assertEqual(str(addr), expected_str_addr) T(x('03d9e529a03f92beba94c85dd869f94388c19c6d7b7c055b3202fee0f70fbfd835'), 'RL5dKQv7ZZYrqSYXNVgy2HvncjcQf8G6at') T(x('03172ea8a57b4c85a2721317d6f99f2d0bfbd624b2faaf465afde6fb7f8bc6a38a'), 'RRHzVuPMUe3r9EhRWUusx5sBKn29SJ93UC') T(CPubKey(x('029ef231f0606dc7b9b4c7af16d0f4a9645b62564f6f167d1f053964b7efff6466')), 'RBmjeJotJSH4mTJpiSj6eQK2kjDEhbRDBm') T(CPubKey(x('02b1f5646f25ecda92bcbd0bf819e1f97b2a61ebad9adfade85cec8bcdc00a2fbf')), 'RLtrHG4X4BbipE4QkqnS16A5uLQt9dxqxp')
def fundrawtransaction(self, given_transaction, *args, **kwargs): """ Make up some inputs for the given transaction. """ # just use any txid here vintxid = lx("99264749804159db1e342a0c8aa3279f6ef4031872051a1e52fb302e51061bef") if isinstance(given_transaction, str): given_bytes = x(given_transaction) elif isinstance(given_transaction, CMutableTransaction): given_bytes = given_transaction.serialize() else: raise FakeRavencoinProxyException("Wrong type passed to fundrawtransaction.") # this is also a clever way to not cause a side-effect in this function transaction = CMutableTransaction.deserialize(given_bytes) for vout_counter in range(0, self._num_fundrawtransaction_inputs): txin = CMutableTxIn(COutPoint(vintxid, vout_counter)) transaction.vin.append(txin) # also allocate a single output (for change) txout = make_txout() transaction.vout.append(txout) transaction_hex = b2x(transaction.serialize()) return {"hex": transaction_hex, "fee": 5000000}
def getblockheader(self, block_hash, verbose=False): """Get block header <block_hash> verbose - If true a dict is returned with the values returned by getblockheader that are not in the block header itself (height, nextblockhash, etc.) Raises IndexError if block_hash is not valid. """ try: block_hash = b2lx(block_hash) except TypeError: raise TypeError('%s.getblockheader(): block_hash must be bytes; got %r instance' % (self.__class__.__name__, block_hash.__class__)) try: r = self._call('getblockheader', block_hash, verbose) except InvalidAddressOrKeyError as ex: raise IndexError('%s.getblockheader(): %s (%d)' % (self.__class__.__name__, ex.error['message'], ex.error['code'])) if verbose: nextblockhash = None if 'nextblockhash' in r: nextblockhash = lx(r['nextblockhash']) return {'confirmations': r['confirmations'], 'height': r['height'], 'mediantime': r['mediantime'], 'nextblockhash': nextblockhash, 'chainwork': x(r['chainwork'])} else: return CBlockHeader.deserialize(unhexlify(r))
def T(hex_scriptpubkey, expected_str_address): scriptPubKey = CScript(x(hex_scriptpubkey)) addr = P2PKHRavencoinAddress.from_scriptPubKey(scriptPubKey) self.assertEqual(str(addr), expected_str_address) # now test that CRavencoinAddressError is raised with accept_non_canonical_pushdata=False with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_scriptPubKey(scriptPubKey, accept_bare_checksig=False)
def test_from_redeemScript(self): def T(script, expected_str_address): addr = P2SHRavencoinAddress.from_redeemScript(script) self.assertEqual(str(addr), expected_str_address) T(CScript(), 'rNgi5iPXJfKYt65YnocubTpm9swCcJwLTY') T(CScript(x('76a914751e76e8199196d454941c45d1b3a323f1433bd688ac')), 'rQy5KSWuzWQwK6ZGJ8wkwLGDb5oCh5FXog')
def test_create_from_string(self): """Create CRavencoinAddress's from strings""" def T(str_addr, expected_bytes, expected_version, expected_class): addr = CRavencoinAddress(str_addr) self.assertEqual(addr.to_bytes(), expected_bytes) self.assertEqual(addr.__class__, expected_class) if isinstance(addr, CBase58RavencoinAddress): self.assertEqual(addr.nVersion, expected_version) elif isinstance(addr, CBech32RavencoinAddress): self.assertEqual(addr.witver, expected_version) T('RXCTT97MGsrguKrtcF7ewXBewdGrx8o1Hg', x('f06d8520dbc8719c46e9b771a1233fcd74e69b2c'), 60, P2PKHRavencoinAddress) T('rMbLFthAWRC6tgR38UEBWXogkizPkGUKhS', x('a87635e97fb76177a3a086efacd841a271b7e8d5'), 122, P2SHRavencoinAddress)
def test_from_invalid_pubkeys(self): """Create P2PKHRavencoinAddress's from invalid pubkeys""" # first test with accept_invalid=True def T(invalid_pubkey, expected_str_addr): addr = P2PKHRavencoinAddress.from_pubkey(invalid_pubkey, accept_invalid=True) self.assertEqual(str(addr), expected_str_addr) T(x(''), 'RRjK2yufHUbEBDSBGny9Xgwz8bxiWBC3m7') T(x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c72'), 'RURg8tQsyiNSQkDQWxjbDDDSJby1qkt5cf') # With accept_invalid=False we should get CRavencoinAddressError's with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_pubkey(x('')) with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_pubkey(x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c72')) with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_pubkey(CPubKey(x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c72')))
def test_create_insert_serialize(self): filter = CBloomFilter(3, 0.01, 0, CBloomFilter.UPDATE_ALL) def T(elem): """Filter contains elem""" elem = x(elem) filter.insert(elem) self.assertTrue(filter.contains(elem)) def F(elem): """Filter does not contain elem""" elem = x(elem) self.assertFalse(filter.contains(elem)) T('99108ad8ed9bb6274d3980bab5a85c048f0950c8') F('19108ad8ed9bb6274d3980bab5a85c048f0950c8') T('b5a2c786d9ef4658287ced5914b37a1b4aa32eee') T('b9300670b4c5366e95b2699e8b18bc75e5f729c5') self.assertEqual(filter.serialize(), x('03614e9b050000000000000001')) deserialized = CBloomFilter.deserialize( x('03614e9b050000000000000001')) self.assertTrue( deserialized.contains( x('99108ad8ed9bb6274d3980bab5a85c048f0950c8'))) self.assertFalse( deserialized.contains( x('19108ad8ed9bb6274d3980bab5a85c048f0950c8'))) self.assertTrue( deserialized.contains( x('b5a2c786d9ef4658287ced5914b37a1b4aa32eee'))) self.assertTrue( deserialized.contains( x('b9300670b4c5366e95b2699e8b18bc75e5f729c5')))
def test_fundrawtransaction_adds_output(self): num_outputs = 5 unfunded_transaction = CMutableTransaction( [], [make_txout() for x in range(0, num_outputs)]) proxy = FakeRavencoinProxy() funded_transaction_hex = proxy.fundrawtransaction( b2x(unfunded_transaction.serialize()))["hex"] funded_transaction = CMutableTransaction.deserialize( x(funded_transaction_hex)) self.assertTrue(len(funded_transaction.vout) > num_outputs) self.assertEqual(len(funded_transaction.vout), num_outputs + 1)
def sendrawtransaction(self, given_transaction): """ Pretend to broadcast and relay the transaction. Return the txid of the given transaction. """ if isinstance(given_transaction, str): given_bytes = x(given_transaction) elif isinstance(given_transaction, CMutableTransaction): given_bytes = given_transaction.serialize() else: raise FakeRavencoinProxyException("Wrong type passed to sendrawtransaction.") transaction = CMutableTransaction.deserialize(given_bytes) return b2lx(transaction.GetHash())
def test(self): if not is_libsec256k1_available(): return use_libsecp256k1_for_signing(True) # Test Vectors for RFC 6979 ECDSA, secp256k1, SHA-256 # (private key, message, expected k, expected signature) test_vectors = [ (0x1, "Satoshi Nakamoto", 0x8F8A276C19F4149656B280621E358CCE24F5F52542772691EE69063B74F15D15, "934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d82442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5"), (0x1, "All those moments will be lost in time, like tears in rain. Time to die...", 0x38AA22D72376B4DBC472E06C3BA403EE0A394DA63FC58D88686C611ABA98D6B3, "8600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21"), (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140, "Satoshi Nakamoto", 0x33A19B60E25FB6F4435AF53A3D42D493644827367E6453928554F43E49AA6F90, "fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d06b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5"), (0xf8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181, "Alan Turing", 0x525A82B70E67874398067543FD84C83D30C175FDC45FDEEE082FE13B1D7CFDF1, "7063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c58dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea"), (0xe91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2, "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!", 0x1F4B84C23A86A221D233F2521BE018D9318639D5B8BBD6374A8A59232D16AD3D, "b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6") ] for vector in test_vectors: secret = CRavencoinSecret.from_secret_bytes(x('{:064x}'.format(vector[0]))) encoded_sig = secret.sign(hashlib.sha256(vector[1].encode('utf8')).digest()) assert(encoded_sig[0] == 0x30) assert(encoded_sig[1] == len(encoded_sig)-2) assert(encoded_sig[2] == 0x02) rlen = encoded_sig[3] rpos = 4 assert(rlen in (32, 33)) if rlen == 33: assert(encoded_sig[rpos] == 0) rpos += 1 rlen -= 1 rval = encoded_sig[rpos:rpos+rlen] spos = rpos+rlen assert(encoded_sig[spos] == 0x02) spos += 1 slen = encoded_sig[spos] assert(slen in (32, 33)) spos += 1 if slen == 33: assert(encoded_sig[spos] == 0) spos += 1 slen -= 1 sval = encoded_sig[spos:spos+slen] sig = b2x(rval + sval) assert(str(sig) == vector[3]) use_libsecp256k1_for_signing(False)
def signrawtransaction(self, given_transaction): """ This method does not actually sign the transaction, but it does return a transaction based on the given transaction. """ if isinstance(given_transaction, str): given_bytes = x(given_transaction) elif isinstance(given_transaction, CMutableTransaction): given_bytes = given_transaction.serialize() else: raise FakeRavencoinProxyException("Wrong type passed to signrawtransaction.") transaction = CMutableTransaction.deserialize(given_bytes) transaction_hex = b2x(transaction.serialize()) return {"hex": transaction_hex}
def test_fundrawtransaction_hex_hash(self): unfunded_transaction = CMutableTransaction( [], [make_txout() for x in range(0, 5)]) proxy = FakeRavencoinProxy() funded_transaction_hex = proxy.fundrawtransaction( b2x(unfunded_transaction.serialize()))["hex"] funded_transaction = CMutableTransaction.deserialize( x(funded_transaction_hex)) self.assertTrue(unfunded_transaction is not funded_transaction) self.assertEqual(type(funded_transaction), type(unfunded_transaction)) self.assertNotEqual(len(funded_transaction.vin), 0) self.assertTrue( len(funded_transaction.vin) > len(unfunded_transaction.vin)) self.assertEqual(type(funded_transaction.vin[0]), CTxIn)
def test_from_non_canonical_scriptPubKey(self): def T(hex_scriptpubkey, expected_str_address): scriptPubKey = CScript(x(hex_scriptpubkey)) addr = P2PKHRavencoinAddress.from_scriptPubKey(scriptPubKey) self.assertEqual(str(addr), expected_str_address) # now test that CRavencoinAddressError is raised with accept_non_canonical_pushdata=False with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_scriptPubKey(scriptPubKey, accept_non_canonical_pushdata=False) T('76a94c14000000000000000000000000000000000000000088ac', 'R9HC5WtHbpoa51NCUAz86XLCmGTbkf45NT') T('76a94d1400000000000000000000000000000000000000000088ac', 'R9HC5WtHbpoa51NCUAz86XLCmGTbkf45NT'), T('76a94e14000000000000000000000000000000000000000000000088ac', 'R9HC5WtHbpoa51NCUAz86XLCmGTbkf45NT') # make sure invalid scripts raise CRavencoinAddressError with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_scriptPubKey(x('76a94c14'))
def test_create_insert_serialize_with_tweak(self): # Same test as bloom_create_insert_serialize, but we add a nTweak of 100 filter = CBloomFilter(3, 0.01, 2147483649, CBloomFilter.UPDATE_ALL) def T(elem): """Filter contains elem""" elem = x(elem) filter.insert(elem) self.assertTrue(filter.contains(elem)) def F(elem): """Filter does not contain elem""" elem = x(elem) self.assertFalse(filter.contains(elem)) T('99108ad8ed9bb6274d3980bab5a85c048f0950c8') F('19108ad8ed9bb6274d3980bab5a85c048f0950c8') T('b5a2c786d9ef4658287ced5914b37a1b4aa32eee') T('b9300670b4c5366e95b2699e8b18bc75e5f729c5') self.assertEqual(filter.serialize(), x('03ce4299050000000100008001'))
def test_signrawtransaction(self): num_outputs = 5 given_transaction = CMutableTransaction( [], [make_txout() for x in range(0, num_outputs)]) proxy = FakeRavencoinProxy() result = proxy.signrawtransaction(given_transaction) self.assertEqual(type(result), dict) self.assertTrue("hex" in result.keys()) result_transaction_hex = result["hex"] result_transaction = CMutableTransaction.deserialize( x(result_transaction_hex)) self.assertTrue(result_transaction is not given_transaction) self.assertTrue(result_transaction.vin is not given_transaction.vin) self.assertTrue(result_transaction.vout is not given_transaction.vout) self.assertEqual(len(result_transaction.vout), len(given_transaction.vout)) self.assertEqual(result_transaction.vout[0].scriptPubKey, given_transaction.vout[0].scriptPubKey)
def test_from_bare_checksig_scriptPubKey(self): def T(hex_scriptpubkey, expected_str_address): scriptPubKey = CScript(x(hex_scriptpubkey)) addr = P2PKHRavencoinAddress.from_scriptPubKey(scriptPubKey) self.assertEqual(str(addr), expected_str_address) # now test that CRavencoinAddressError is raised with accept_non_canonical_pushdata=False with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_scriptPubKey(scriptPubKey, accept_bare_checksig=False) # compressed T('21000000000000000000000000000000000000000000000000000000000000000000ac', 'RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY') # uncompressed T('410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac', 'RYcSf1PAjycb31WBycYukQACU1iZP3hLS7') # non-canonical encoding T('4c21000000000000000000000000000000000000000000000000000000000000000000ac', 'RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY') # odd-lengths are *not* accepted with self.assertRaises(CRavencoinAddressError): P2PKHRavencoinAddress.from_scriptPubKey(x('2200000000000000000000000000000000000000000000000000000000000000000000ac'))
def T(elem): """Filter contains elem""" elem = x(elem) filter.insert(elem) self.assertTrue(filter.contains(elem))
def __init__(self, data=None): self._asset_type = None self._asset_name = "" self._amount = 0 self._divisor = None self._reissuable = None self._ipfshash = "" self.data = None # raw data (bytes) isnull = False if data is not None: if type(data) is str: # pass binary or hex string to initialise object # data must exclude the op_rvn_asset bytecode itself # and the first (script length) and last (75 = OP_DROP) bytes data = x(data) self.data = data try: prefix = struct.unpack('< 3s', data[:3])[0] assert (prefix.decode("ascii") == "rvn") except Exception as e: self.asset_type = 0 return # treat as nullassetdata self.asset_type, name_length = struct.unpack('< B B', data[3:5]) if self.asset_type in ("new", "admin", "reissue", "transfer"): # asset name unpack_data = data[5:5 + name_length] self._asset_name = struct.unpack('< {}s'.format(name_length), unpack_data) self._asset_name = self._asset_name[0].decode('ascii') if self._asset_type == 0x6f: # admin asset return unpack_data = data[5 + name_length:5 + name_length + 8] self._amount = struct.unpack('< q', unpack_data)[0] if self.asset_type in ("new", "reissue"): unpack_data = data[5 + name_length + 8:] idx = 0 if len(unpack_data) > 0: self._divisor = struct.unpack('<B', unpack_data[idx:idx + 1])[0] idx += 1 if len(unpack_data) > 1: self._reissuable = struct.unpack( '<B', unpack_data[idx:idx + 1])[0] idx += 1 if len(unpack_data) > 2 and self.asset_type == "new": has_ipfs = struct.unpack('<?', unpack_data[idx:idx + 1])[0] idx += 1 if len(unpack_data) > 3: ipfs_bytelength = struct.unpack('<B', unpack_data[idx:idx + 1])[0] if ipfs_bytelength == 84: idx += 1 ipfs_bytelength = struct.unpack( '<B', unpack_data[idx:idx + 1])[0] idx += 1 ipfs_data = unpack_data[idx:] self._ipfshash = struct.unpack( '<{}s'.format(len(ipfs_data)), ipfs_data)[0] if len(self._ipfshash) == 34: self._ipfshash = encode(self._ipfshash) else: self._ipfshash = self._ipfshash.hex()
def T(hex_pubkey, is_valid, is_fullyvalid, is_compressed): key = CPubKey(x(hex_pubkey)) self.assertEqual(key.is_valid, is_valid) self.assertEqual(key.is_fullyvalid, is_fullyvalid) self.assertEqual(key.is_compressed, is_compressed)
def T(expected, seed, data): self.assertEqual(MurmurHash3(seed, x(data)), expected)
def T(hex_scriptpubkey, expected_str_address, expected_class): scriptPubKey = CScript(x(hex_scriptpubkey)) addr = CRavencoinAddress.from_scriptPubKey(scriptPubKey) self.assertEqual(str(addr), expected_str_address) self.assertEqual(addr.__class__, expected_class)
def F(elem): """Filter does not contain elem""" elem = x(elem) self.assertFalse(filter.contains(elem))