4141
4242DEFAULT_HTTP_TIMEOUT = 30
4343
44- unhexlify = lambda h : binascii .unhexlify (h .encode ('utf8' ))
45- hexlify = lambda b : binascii .hexlify (b ).decode ('utf8' )
44+ def unhexlify_str (h ):
45+ """
46+ Converts a string containing hexadecimal encoding into a bytes-object.
47+
48+ It works by encoding the given string h as ASCII, then interpreting each of
49+ its two-character ASCII tuples as bytes:
50+ - "00" to byte 0
51+ - "ff" to byte 255
52+ - "FF" also to byte 255
53+
54+ The string must only contain characters in the ranges 0-9, a-f and A-F.
55+
56+ If the string contains characters not in ASCII,
57+ UnicodeEncodeError is raised.
58+ If the string contains out-of-range ASCII characters,
59+ binascii.Error is raised.
60+ If number of encoded ASCII bytes is odd,
61+ binascii.Error is raised.
62+ """
63+ return binascii .unhexlify (h .encode ('ascii' ))
64+
65+ def hexlify_str (b ):
66+ """
67+ Given an arbitrary bytes-like object, returns a string (that would encode
68+ as ASCII) containing the hex-representation of the bytes-like object.
69+
70+ Always succeeds.
71+ """
72+ return binascii .hexlify (b ).decode ('ascii' )
4673
4774
4875class JSONRPCError (Exception ):
@@ -365,10 +392,10 @@ def fundrawtransaction(self, tx, include_watching=False):
365392 'changepos': Position of added change output, or -1,
366393 }
367394 """
368- hextx = hexlify (tx .serialize ())
395+ hextx = hexlify_str (tx .serialize ())
369396 r = self ._call ('fundrawtransaction' , hextx , include_watching )
370397
371- r ['tx' ] = CTransaction .deserialize (unhexlify (r ['hex' ]))
398+ r ['tx' ] = CTransaction .deserialize (unhexlify_str (r ['hex' ]))
372399 del r ['hex' ]
373400
374401 r ['fee' ] = int (r ['fee' ] * COIN )
@@ -456,7 +483,7 @@ def getblockheader(self, block_hash, verbose=False):
456483 'nextblockhash' :nextblockhash ,
457484 'chainwork' :x (r ['chainwork' ])}
458485 else :
459- return CBlockHeader .deserialize (unhexlify (r ))
486+ return CBlockHeader .deserialize (unhexlify_str (r ))
460487
461488
462489 def getblock (self , block_hash ):
@@ -477,7 +504,7 @@ def getblock(self, block_hash):
477504 except InvalidAddressOrKeyError as ex :
478505 raise IndexError ('%s.getblock(): %s (%d)' %
479506 (self .__class__ .__name__ , ex .error ['message' ], ex .error ['code' ]))
480- return CBlock .deserialize (unhexlify (r ))
507+ return CBlock .deserialize (unhexlify_str (r ))
481508
482509 def getblockcount (self ):
483510 """Return the number of blocks in the longest block chain"""
@@ -556,7 +583,7 @@ def getrawtransaction(self, txid, verbose=False):
556583 raise IndexError ('%s.getrawtransaction(): %s (%d)' %
557584 (self .__class__ .__name__ , ex .error ['message' ], ex .error ['code' ]))
558585 if verbose :
559- r ['tx' ] = CTransaction .deserialize (unhexlify (r ['hex' ]))
586+ r ['tx' ] = CTransaction .deserialize (unhexlify_str (r ['hex' ]))
560587 del r ['hex' ]
561588 del r ['txid' ]
562589 del r ['version' ]
@@ -565,7 +592,7 @@ def getrawtransaction(self, txid, verbose=False):
565592 del r ['vout' ]
566593 r ['blockhash' ] = lx (r ['blockhash' ]) if 'blockhash' in r else None
567594 else :
568- r = CTransaction .deserialize (unhexlify (r ))
595+ r = CTransaction .deserialize (unhexlify_str (r ))
569596
570597 return r
571598
@@ -613,7 +640,7 @@ def gettxout(self, outpoint, includemempool=True):
613640 raise IndexError ('%s.gettxout(): unspent txout %r not found' % (self .__class__ .__name__ , outpoint ))
614641
615642 r ['txout' ] = CTxOut (int (r ['value' ] * COIN ),
616- CScript (unhexlify (r ['scriptPubKey' ]['hex' ])))
643+ CScript (unhexlify_str (r ['scriptPubKey' ]['hex' ])))
617644 del r ['value' ]
618645 del r ['scriptPubKey' ]
619646 r ['bestblock' ] = lx (r ['bestblock' ])
@@ -653,7 +680,7 @@ def listunspent(self, minconf=0, maxconf=9999999, addrs=None):
653680 unspent ['address' ] = CBitcoinAddress (unspent ['address' ])
654681 except KeyError :
655682 pass
656- unspent ['scriptPubKey' ] = CScript (unhexlify (unspent ['scriptPubKey' ]))
683+ unspent ['scriptPubKey' ] = CScript (unhexlify_str (unspent ['scriptPubKey' ]))
657684 unspent ['amount' ] = int (unspent ['amount' ] * COIN )
658685 r2 .append (unspent )
659686 return r2
@@ -669,7 +696,7 @@ def sendrawtransaction(self, tx, allowhighfees=False):
669696
670697 allowhighfees - Allow even if fees are unreasonably high.
671698 """
672- hextx = hexlify (tx .serialize ())
699+ hextx = hexlify_str (tx .serialize ())
673700 r = None
674701 if allowhighfees :
675702 r = self ._call ('sendrawtransaction' , hextx , True )
@@ -699,9 +726,9 @@ def signrawtransaction(self, tx, *args):
699726
700727 FIXME: implement options
701728 """
702- hextx = hexlify (tx .serialize ())
729+ hextx = hexlify_str (tx .serialize ())
703730 r = self ._call ('signrawtransaction' , hextx , * args )
704- r ['tx' ] = CTransaction .deserialize (unhexlify (r ['hex' ]))
731+ r ['tx' ] = CTransaction .deserialize (unhexlify_str (r ['hex' ]))
705732 del r ['hex' ]
706733 return r
707734
@@ -711,9 +738,9 @@ def signrawtransactionwithwallet(self, tx, *args):
711738
712739 FIXME: implement options
713740 """
714- hextx = hexlify (tx .serialize ())
741+ hextx = hexlify_str (tx .serialize ())
715742 r = self ._call ('signrawtransactionwithwallet' , hextx , * args )
716- r ['tx' ] = CTransaction .deserialize (unhexlify (r ['hex' ]))
743+ r ['tx' ] = CTransaction .deserialize (unhexlify_str (r ['hex' ]))
717744 del r ['hex' ]
718745 return r
719746
@@ -723,7 +750,7 @@ def submitblock(self, block, params=None):
723750 params is optional and is currently ignored by bitcoind. See
724751 https://en.bitcoin.it/wiki/BIP_0022 for full specification.
725752 """
726- hexblock = hexlify (block .serialize ())
753+ hexblock = hexlify_str (block .serialize ())
727754 if params is not None :
728755 return self ._call ('submitblock' , hexblock , params )
729756 else :
@@ -735,7 +762,7 @@ def validateaddress(self, address):
735762 if r ['isvalid' ]:
736763 r ['address' ] = CBitcoinAddress (r ['address' ])
737764 if 'pubkey' in r :
738- r ['pubkey' ] = unhexlify (r ['pubkey' ])
765+ r ['pubkey' ] = unhexlify_str (r ['pubkey' ])
739766 return r
740767
741768 def unlockwallet (self , password , timeout = 60 ):
0 commit comments