forked from bitcoin-abe/bitcoin-abe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.py
199 lines (162 loc) · 5.77 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# Copyright(C) 2011,2012,2013,2014 by Abe developers.
# Copyright (c) 2010 Gavin Andresen
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/agpl.html>.
#
# Misc util routines
#
import re
import base58
import Crypto.Hash.SHA256 as SHA256
try:
import Crypto.Hash.RIPEMD as RIPEMD160
except Exception:
import ripemd_via_hashlib as RIPEMD160
# This function comes from bitcointools, bct-LICENSE.txt.
def determine_db_dir():
import os
import os.path
import platform
if platform.system() == "Darwin":
return os.path.expanduser("~/Library/Application Support/Bitcoin/")
elif platform.system() == "Windows":
return os.path.join(os.environ['APPDATA'], "Bitcoin")
return os.path.expanduser("~/.bitcoin")
# This function comes from bitcointools, bct-LICENSE.txt.
def long_hex(bytes):
return bytes.encode('hex_codec')
# This function comes from bitcointools, bct-LICENSE.txt.
def short_hex(bytes):
t = bytes.encode('hex_codec')
if len(t) < 11:
return t
return t[0:4]+"..."+t[-4:]
NULL_HASH = "\0" * 32
GENESIS_HASH_PREV = NULL_HASH
def sha256(s):
return SHA256.new(s).digest()
def double_sha256(s):
return sha256(sha256(s))
def sha3_256(s):
import hashlib
import sys
if sys.version_info < (3, 4):
import sha3
return hashlib.sha3_256(s).digest()
def pubkey_to_hash(pubkey):
return RIPEMD160.new(SHA256.new(pubkey).digest()).digest()
def calculate_target(nBits):
# cf. CBigNum::SetCompact in bignum.h
shift = 8 * (((nBits >> 24) & 0xff) - 3)
bits = nBits & 0x7fffff
sign = -1 if (nBits & 0x800000) else 1
return sign * (bits << shift if shift >= 0 else bits >> -shift)
def target_to_difficulty(target):
return ((1 << 224) - 1) * 1000 / (target + 1) / 1000.0
def calculate_difficulty(nBits):
return target_to_difficulty(calculate_target(nBits))
def work_to_difficulty(work):
return work * ((1 << 224) - 1) * 1000 / (1 << 256) / 1000.0
def target_to_work(target):
# XXX will this round using the same rules as C++ Bitcoin?
return int((1 << 256) / (target + 1))
def calculate_work(prev_work, nBits):
if prev_work is None:
return None
return prev_work + target_to_work(calculate_target(nBits))
def work_to_target(work):
return int((1 << 256) / work) - 1
def get_search_height(n):
if n < 2:
return None
if n & 1:
return n >> 1 if n & 2 else n - (n >> 2)
bit = 2
while (n & bit) == 0:
bit <<= 1
return n - bit
ADDRESS_RE = re.compile('[1-9A-HJ-NP-Za-km-z]{26,}\\Z')
def possible_address(string):
return ADDRESS_RE.match(string)
def hash_to_address(version, hash):
vh = version + hash
return base58.b58encode(vh + double_sha256(vh)[:4])
def decode_check_address(address):
if possible_address(address):
version, hash = decode_address(address)
if hash_to_address(version, hash) == address:
return version, hash
return None, None
def decode_address(addr):
bytes = base58.b58decode(addr, None)
if len(bytes) < 25:
bytes = ('\0' * (25 - len(bytes))) + bytes
return bytes[:-24], bytes[-24:-4]
class JsonrpcException(Exception):
def __init__(ex, error, method, params):
Exception.__init__(ex)
ex.code = error['code']
ex.message = error['message']
ex.data = error.get('data')
ex.method = method
ex.params = params
def __str__(ex):
return ex.method + ": " + ex.message + " (code " + str(ex.code) + ")"
class JsonrpcMethodNotFound(JsonrpcException):
pass
def jsonrpc(url, method, *params):
import json, urllib
postdata = json.dumps({"jsonrpc": "2.0",
"method": method, "params": params, "id": "x"})
respdata = urllib.urlopen(url, postdata).read()
resp = json.loads(respdata)
if resp.get('error') is not None:
if resp['error']['code'] == -32601:
raise JsonrpcMethodNotFound(resp['error'], method, params)
raise JsonrpcException(resp['error'], method, params)
return resp['result']
def str_to_ds(s):
import BCDataStream
ds = BCDataStream.BCDataStream()
ds.write(s)
return ds
class CmdLine(object):
def __init__(self, argv, conf=None):
self.argv = argv
if conf is None:
self.conf = {}
else:
self.conf = conf.copy()
def usage(self):
return "Sorry, no help is available."
def init(self):
import DataStore, readconf, logging, sys
self.conf.update({ "debug": None, "logging": None })
self.conf.update(DataStore.CONFIG_DEFAULTS)
args, argv = readconf.parse_argv(self.argv, self.conf, strict=False)
if argv and argv[0] in ('-h', '--help'):
print self.usage()
return None, []
logging.basicConfig(
stream=sys.stdout, level=logging.DEBUG, format="%(message)s")
if args.logging is not None:
import logging.config as logging_config
logging_config.dictConfig(args.logging)
store = DataStore.new(args)
return store, argv
# Abstract hex-binary conversions for eventual porting to Python 3.
def hex2b(s):
return s.decode('hex')
def b2hex(b):
return b.encode('hex')