Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix burn and Fix transaction_by_scripthash function #156

Merged
merged 2 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions electrumx/lib/atomicals_blueprint_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ def calculate_outputs_to_color_for_ft_atomical_ids(tx, ft_atomicals, sort_by_fif
# Erase the potential for safety
potential_atomical_ids_to_output_idxs_map = {}
non_clean_output_slots = True
if remaining_value_from_assign > 0:
fts_burned[atomical_id] = get_nominal_token_value(remaining_value_from_assign, use_exponent)
break

# If the output slots did not fit cleanly, then default to just assigning everything from the 0'th output index
Expand Down
43 changes: 31 additions & 12 deletions electrumx/server/block_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,19 @@ def __init__(self, env: 'Env', db: DB, daemon: Daemon, notifications: 'Notificat
self.atomicals_rpc_format_cache = pylru.lrucache(100000)
self.atomicals_rpc_general_cache = pylru.lrucache(100000)
self.atomicals_dft_mint_count_cache = pylru.lrucache(1000) # tracks number of minted tokens per dft mint to make processing faster per blocks

self.op_list = {
"mint-dft": 1, "mint-ft": 2, "mint-nft": 3, "mint-nft-realm": 4,
"mint-nft-subrealm": 5, "mint-nft-container": 6, "mint-nft-dmitem": 7,
"dft": 20, "dat": 21, "split": 22, "splat": 23,
"seal": 24, "evt": 25, "mod": 26,
"transfer": 30,
"payment-subrealm": 40, "payment-dmitem": 41,
"mint-dft-failed": 51, "mint-ft-failed": 52, "mint-nft-failed": 53, "mint-nft-realm-failed": 54,
"mint-nft-subrealm-failed": 55, "mint-nft-container-failed": 56, "mint-nft-dmitem-failed": 57,
"invalid-mint": 59,
"burn": 70,
}

async def run_in_thread_with_lock(self, func, *args):
# Run in a thread to prevent blocking. Shielded so that
# cancellations from shutdown don't lose work - when the task
Expand Down Expand Up @@ -951,17 +963,7 @@ def delete_state_data(self, db_key_prefix, db_key_suffix, expected_entry_value):

# Function to cache and eventually flush the op
def put_op_data(self, tx_num, tx_hash, op):
op_list = {
"mint-dft": 1, "mint-ft": 2, "mint-nft": 3, "mint-nft-realm": 4,
"mint-nft-subrealm": 5, "mint-nft-container": 6, "mint-nft-item": 7,
"dft": 20, "dat": 21, "split": 22, "splat": 23,
"seal": 24, "evt": 25, "mod": 26,
"transfer": 30, "invalid-mint": 31,
"payment-subrealm": 40, "payment-dmitem": 41,
"mint-dft-failed": 51, "mint-ft-failed": 52, "mint-nft-failed": 53, "mint-nft-realm-failed": 54,
"mint-nft-subrealm-failed": 55, "mint-nft-container-failed": 56, "mint-nft-item-failed": 57,
}
op_num = op_list.get(op)
op_num = self.op_list.get(op)
if op_num:
op_prefix_key = b'op' + pack_le_uint64(tx_num)
self.logger.debug(f'add the {op} op transaction detail for {hash_to_hex_str(tx_hash)}')
Expand Down Expand Up @@ -1466,6 +1468,16 @@ def create_or_delete_atomical(self, operations_found_at_inputs, atomicals_spent_
return None
if not Delete:
if not self.validate_and_create_nft_mint_utxo(mint_info, txout, height, tx_hash):
if mint_info.get('$request_realm'):
self.put_op_data(tx_num, tx_hash, "mint-nft-realm-failed")
elif mint_info.get('$request_subrealm'):
self.put_op_data(tx_num, tx_hash, "mint-nft-subrealm-failed")
elif mint_info.get('$request_container'):
self.put_op_data(tx_num, tx_hash, "mint-nft-container-failed")
elif mint_info.get('$request_dmitem'):
self.put_op_data(tx_num, tx_hash, "mint-nft-dmitem-failed")
else:
self.put_op_data(tx_num, tx_hash, "mint-nft-failed")
self.logger.info(f'create_or_delete_atomical: validate_and_create_nft_mint_utxo returned FALSE in Transaction {hash_to_hex_str(tx_hash)}. Skipping...')
return None
else:
Expand Down Expand Up @@ -1499,6 +1511,10 @@ def create_or_delete_atomical(self, operations_found_at_inputs, atomicals_spent_
if not Delete:
if not self.validate_and_create_ft_mint_utxo(mint_info, tx_hash):
self.logger.info(f'create_or_delete_atomical: validate_and_create_ft_mint_utxo returned FALSE in Transaction {hash_to_hex_str(tx_hash)}. Skipping...')
if mint_info['subtype'] == 'decentralized':
self.put_op_data(tx_num, tx_hash, "mint-dft-failed")
else:
self.put_op_data(tx_num, tx_hash, "mint-ft-failed")
return None
else:
if mint_info['subtype'] == 'decentralized':
Expand Down Expand Up @@ -1720,6 +1736,7 @@ def color_atomicals_outputs(self, operations_found_at_inputs, atomicals_spent_at

# Log that there were tokens burned due to not being cleanly assigned
if blueprint_builder.get_are_fts_burned():
self.put_op_data(tx_num, tx_hash, "burn")
self.logger.debug(f'color_atomicals_outputs:are_fts_burned=True tx_hash={tx_hash} ft_output_blueprint={ft_output_blueprint}')

return blueprint_builder
Expand Down Expand Up @@ -2724,9 +2741,11 @@ def create_or_delete_decentralized_mint_output(self, atomicals_operations_found_
return dmt_mint_atomical_id
else:
self.logger.debug(f'create_or_delete_decentralized_mint_outputs found invalid mint operation because it is minted out completely. {hash_to_hex_str(tx_hash)}. Ignoring...')
self.put_op_data(tx_num, tx_hash, "mint-dft-failed")
return None
else:
self.logger.warning(f'create_or_delete_decentralized_mint_outputs: found invalid mint operation in {hash_to_hex_str(tx_hash)} for {ticker} because incorrect txout.value {txout.value} when expected {mint_amount}')
self.put_op_data(tx_num, tx_hash, "mint-dft-failed")
return None

def is_atomicals_activated(self, height):
Expand Down
21 changes: 6 additions & 15 deletions electrumx/server/http_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,7 @@ def __init__(self, session_mgr, db, mempool, peer_mgr, kind):
self.mempool_statuses = {}
self.sv_seen = False
self.MAX_CHUNK_SIZE = 2016
self.hashX_subs = {}
self.op_list = {
"mint-dft": 1, "mint-ft": 2, "mint-nft": 3, "mint-nft-realm": 4,
"mint-nft-subrealm": 5, "mint-nft-container": 6, "mint-nft-item": 7,
"dft": 20, "dat": 21, "split": 22, "splat": 23,
"seal": 24, "evt": 25, "mod": 26,
"transfer": 30, "invalid-mint": 31,
"payment-subrealm": 40, "payment-dmitem": 41,
"mint-dft-failed": 51, "mint-ft-failed": 52, "mint-nft-failed": 53, "mint-nft-realm-failed": 54,
"mint-nft-subrealm-failed": 55, "mint-nft-container-failed": 56, "mint-nft-item-failed": 57,
}
self.hashX_subs = {}

async def format_params(self, request):
if request.method == "GET":
Expand Down Expand Up @@ -2235,7 +2225,7 @@ async def transaction_by_atomical_id(self, request):

res = []
if op_type:
op = self.op_list.get(op_type, None)
op = self.session_mgr.bp.op_list.get(op_type, None)
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, op, reverse)
else:
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, None, reverse)
Expand All @@ -2256,18 +2246,19 @@ async def transaction_by_scripthash(self, request):
op_type = params.get(3, None)
reverse = params.get(4, True)

res = []
hashX = scripthash_to_hashX(scripthash)
res = []
if op_type:
op = self.op_list.get(op_type, None)
op = self.session_mgr.bp.op_list.get(op_type, None)
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, op, reverse)
else:
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, None, reverse)

for history in history_data:
tx_hash, tx_height = self.db.fs_tx_hash(history["tx_num"])
data = await self.get_transaction_detail(hash_to_hex_str(tx_hash), tx_height, history["tx_num"])
if data and data["op"]:
if (op_type and data["op"] == op_type) or not op_type:
if data["op"] and (data["op"] == op_type or not op_type):
res.append(data)
return {"result": res, "total": total, "limit": limit, "offset": offset}

Expand Down
29 changes: 17 additions & 12 deletions electrumx/server/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,15 @@ def __init__(
self.session_event = Event()
self.op_list = {
"mint-dft": 1, "mint-ft": 2, "mint-nft": 3, "mint-nft-realm": 4,
"mint-nft-subrealm": 5, "mint-nft-container": 6, "mint-nft-item": 7,
"mint-nft-subrealm": 5, "mint-nft-container": 6, "mint-nft-dmitem": 7,
"dft": 20, "dat": 21, "split": 22, "splat": 23,
"seal": 24, "evt": 25, "mod": 26,
"transfer": 30, "invalid-mint": 31,
"transfer": 30,
"payment-subrealm": 40, "payment-dmitem": 41,
"mint-dft-failed": 51, "mint-ft-failed": 52, "mint-nft-failed": 53, "mint-nft-realm-failed": 54,
"mint-nft-subrealm-failed": 55, "mint-nft-container-failed": 56, "mint-nft-item-failed": 57,
"mint-nft-subrealm-failed": 55, "mint-nft-container-failed": 56, "mint-nft-dmitem-failed": 57,
"invalid-mint": 59,
"burn": 70,
}

# Set up the RPC request handlers
Expand Down Expand Up @@ -1035,6 +1037,8 @@ async def get_history_op(self, hashX, limit=10, offset=0, op=None, reverse=True)
history_data.sort(key=lambda x: x['tx_num'], reverse=reverse)
if op:
history_data = list(filter(lambda x: x["op"] == op, history_data))
else:
history_data = list(filter(lambda x: x["op"], history_data))
return history_data[offset:limit+offset], len(history_data)

async def _notify_sessions(self, height, touched):
Expand All @@ -1048,11 +1052,11 @@ async def _notify_sessions(self, height, touched):
for hashX in set(cache).intersection(touched):
del cache[hashX]
for hashX in set(op_cache).intersection(touched):
del op_cache[hashX]
if self.notified_height == await self.daemon.height():
time.sleep(20)
background_task = asyncio.create_task(self.get_history_op(hashX, 10, 0, None, False))
await background_task
op_cache.pop(hashX, None)
self.logger.info(f"refresh op cache {self.notified_height}")
time.sleep(2)
background_task = asyncio.create_task(self.get_history_op(hashX, 10, 0, None, True))
await background_task

for session in self.sessions:
if self._task_group.joined: # this can happen during shutdown
Expand Down Expand Up @@ -3035,7 +3039,7 @@ async def transaction_by_atomical_id(self, compact_atomical_id_or_atomical_numbe

res = []
if op_type:
op = self.session_mgr.op_list.get(op_type, None)
op = self.session_mgr.bp.op_list.get(op_type, None)
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, op, reverse)
else:
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, None, reverse)
Expand All @@ -3049,18 +3053,19 @@ async def transaction_by_atomical_id(self, compact_atomical_id_or_atomical_numbe

# get transaction by scripthash
async def transaction_by_scripthash(self, scripthash, limit=10, offset=0, op_type=None, reverse=True):
res = []
hashX = scripthash_to_hashX(scripthash)
res = []
if op_type:
op = self.session_mgr.op_list.get(op_type, None)
op = self.session_mgr.bp.op_list.get(op_type, None)
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, op, reverse)
else:
history_data, total = await self.session_mgr.get_history_op(hashX, limit, offset, None, reverse)

for history in history_data:
tx_hash, tx_height = self.db.fs_tx_hash(history["tx_num"])
data = await self.get_transaction_detail(hash_to_hex_str(tx_hash), tx_height, history["tx_num"])
if data and data["op"]:
if (op_type and data["op"] == op_type) or not op_type:
if data["op"] and (data["op"] == op_type or not op_type):
res.append(data)
return {"result": res, "total": total, "limit": limit, "offset": offset}

Expand Down
Loading