mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-04-24 03:45:38 +08:00
add code to get a name and its history using pagination, with a fallback to get_name_blockchain_record()
This commit is contained in:
@@ -1023,7 +1023,10 @@ def get_name_record(name, include_history=False, include_expired=False, include_
|
||||
lastblock = None
|
||||
try:
|
||||
if include_history:
|
||||
resp = proxy.get_name_blockchain_record(name)
|
||||
resp = get_name_and_history(name, proxy=proxy)
|
||||
if 'error' in resp:
|
||||
# fall back to legacy path
|
||||
resp = proxy.get_name_blockchain_record(name)
|
||||
else:
|
||||
resp = proxy.get_name_record(name)
|
||||
|
||||
@@ -2853,6 +2856,164 @@ def get_block_from_consensus(consensus_hash, hostport=None, proxy=None):
|
||||
return resp['block_id']
|
||||
|
||||
|
||||
def get_name_history_page(name, page, hostport=None, proxy=None):
|
||||
"""
|
||||
Get a page of the name's history
|
||||
Returns {'status': True, 'history': ..., 'indexing': ..., 'lastblock': ...} on success
|
||||
Returns {'error': ...} on error
|
||||
"""
|
||||
assert hostport or proxy, 'Need hostport or proxy'
|
||||
if proxy is None:
|
||||
proxy = connect_hostport(hostport)
|
||||
|
||||
hist_schema = {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
'^[0-9]+$': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': OP_HISTORY_SCHEMA['properties'],
|
||||
'required': [
|
||||
'op',
|
||||
'opcode',
|
||||
'txid',
|
||||
'vtxindex',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
hist_resp_schema = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'history': hist_schema,
|
||||
},
|
||||
'required': [ 'history' ],
|
||||
}
|
||||
|
||||
resp_schema = json_response_schema(hist_resp_schema)
|
||||
resp = {}
|
||||
lastblock = None
|
||||
indexin = None
|
||||
|
||||
try:
|
||||
_resp = proxy.get_name_history_page(name, page)
|
||||
resp = json_validate(resp_schema, _resp)
|
||||
if json_is_error(resp):
|
||||
return resp
|
||||
|
||||
lastblock = _resp['lastblock']
|
||||
indexing = _resp['indexing']
|
||||
|
||||
except ValidationError as e:
|
||||
resp = json_traceback(resp.get('error'))
|
||||
return resp
|
||||
|
||||
except Exception as ee:
|
||||
if BLOCKSTACK_DEBUG:
|
||||
log.exception(ee)
|
||||
|
||||
log.error("Caught exception while connecting to Blockstack node: {}".format(ee))
|
||||
resp = {'error': 'Failed to contact Blockstack node. Try again with `--debug`.'}
|
||||
return resp
|
||||
|
||||
return {'status': True, 'history': resp['history'], 'lastblock': lastblock, 'indexing': indexing}
|
||||
|
||||
|
||||
def name_history_merge(h1, h2):
|
||||
"""
|
||||
Given two name histories (grouped by block), merge them.
|
||||
"""
|
||||
ret = {}
|
||||
blocks_1 = [int(b) for b in h1.keys()]
|
||||
blocks_2 = [int(b) for b in h2.keys()]
|
||||
|
||||
# find overlapping blocks
|
||||
overlap = list(set(blocks_1).intersection(set(blocks_2)))
|
||||
if len(overlap) > 0:
|
||||
for b in overlap:
|
||||
h = h1[str(b)] + h2[str(b)]
|
||||
h.sort(lambda v1, v2: -1 if v1['vtxindex'] < v2['vtxindex'] else 1)
|
||||
|
||||
uniq = []
|
||||
last_vtxindex = None
|
||||
for i in range(0, len(h)):
|
||||
if h[i]['vtxindex'] != last_vtxindex:
|
||||
uniq.append(h[i])
|
||||
last_vtxindex = h[i]['vtxindex']
|
||||
|
||||
ret[str(b)] = uniq
|
||||
|
||||
all_blocks = list(set(blocks_1 + blocks_2))
|
||||
for b in all_blocks:
|
||||
if b in overlap:
|
||||
continue
|
||||
|
||||
if b in blocks_1:
|
||||
ret[str(b)] = h1[str(b)]
|
||||
else:
|
||||
ret[str(b)] = h2[str(b)]
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def get_name_history(name, hostport=None, proxy=None):
|
||||
"""
|
||||
Get the full history of a name
|
||||
Returns {'status': True, 'history': ...} on success, where history is grouped by block
|
||||
Returns {'error': ...} on error
|
||||
"""
|
||||
assert hostport or proxy, 'Need hostport or proxy'
|
||||
if proxy is None:
|
||||
proxy = connect_hostport(hostport)
|
||||
|
||||
hist = {}
|
||||
indexing = None
|
||||
lastblock = None
|
||||
|
||||
for i in range(0, 10000): # this is obviously too big
|
||||
resp = get_name_history_page(name, i, proxy=proxy)
|
||||
if 'error' in resp:
|
||||
return resp
|
||||
|
||||
indexing = resp['indexing']
|
||||
lastblock = resp['lastblock']
|
||||
|
||||
if len(resp['history']) == 0:
|
||||
# caught up
|
||||
break
|
||||
|
||||
hist = name_history_merge(hist, resp['history'])
|
||||
|
||||
return {'status': True, 'history': hist, 'indexing': indexing, 'lastblock': lastblock}
|
||||
|
||||
|
||||
def get_name_and_history(name, include_expired=False, include_grace=True, hostport=None, proxy=None):
|
||||
"""
|
||||
Get the current name record and its history
|
||||
(this is a replacement for proxy.get_name_blockchain_record())
|
||||
Return {'status': True, 'record': ...} on success, where .record.history is defined as {block_height: [{history}, {history}, ...], ...}
|
||||
Return {'error': ...} on error
|
||||
"""
|
||||
assert hostport or proxy, 'Need hostport or proxy'
|
||||
if proxy is None:
|
||||
proxy = connect_hostport(hostport)
|
||||
|
||||
hist = get_name_history(name, proxy=proxy)
|
||||
if 'error' in hist:
|
||||
return hist
|
||||
|
||||
# just the name
|
||||
rec = get_name_record(name, include_history=False, include_expired=include_expired, include_grace=include_grace, proxy=proxy)
|
||||
if 'error' in rec:
|
||||
return rec
|
||||
|
||||
rec['history'] = hist['history']
|
||||
return {'status': True, 'record': rec, 'lastblock': hist['lastblock'], 'indexing': hist['indexing']}
|
||||
|
||||
|
||||
def get_name_at(name, block_id, include_expired=False, hostport=None, proxy=None):
|
||||
"""
|
||||
Get the name as it was at a particular height.
|
||||
|
||||
Reference in New Issue
Block a user