Skip to content

Commit

Permalink
Add max_mints_global for perpetual tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
Ardwin authored and Ardwin committed Jan 29, 2024
1 parent 22cd773 commit f2f0b4d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 16 deletions.
17 changes: 12 additions & 5 deletions electrumx/lib/util_atomicals.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ class AtomicalsValidationError(Exception):
DFT_MINT_MAX_MIN_COUNT = 1
# The maximum number (legacy) of DFT max_mints. Set at 500,000 mints mainly for efficieny reasons in legacy.
DFT_MINT_MAX_MAX_COUNT_LEGACY = 500000
# The maximum number of DFT max_mints (after legacy 'DENSITY' update). Set at 10,000,000 max mints.
DFT_MINT_MAX_MAX_COUNT_DENSITY = 10000000
# The maximum number of DFT max_mints (after legacy 'DENSITY' update). Set at 21,000,000 max mints.
DFT_MINT_MAX_MAX_COUNT_DENSITY = 21000000

# This would never change, but we put it as a constant for clarity
DFT_MINT_HEIGHT_MIN = 0
Expand Down Expand Up @@ -785,18 +785,25 @@ def populate_args_meta_ctx_init(mint_info, op_found_payload):
logger.warning(f'DFT init has invalid brs {hash_to_hex_str(tx_hash)}, {brs}. Skipping...')
return None, None

mint_info['$mint_mode'] = 'infinite'
mint_info['$mint_mode'] = 'perpetual'
mint_info['$mint_bitworkc_inc'] = bci
mint_info['$mint_bitworkr_inc'] = bri
mint_info['$mint_bitworkc_start'] = bcs
mint_info['$mint_bitworkr_start'] = brs
mint_info['$mint_bitwork_vec'] = bv

# When in infinite minting mode limit the max mints per phase
# When in perpetual minting mode limit the max mints per phase
max_mints = mint_info['$max_mints']
if max_mints > 100000:
logger.warning(f'DFT init has invalid max_mints must be <= 100000 with infinite mining {hash_to_hex_str(tx_hash)}, {max_mints}. Skipping...')
logger.warning(f'DFT init has invalid max_mints must be <= 100000 with perpetual mining {hash_to_hex_str(tx_hash)}, {max_mints}. Skipping...')
return None, None

max_mints_global = mint_info['args'].get('maxg')
if max_mints_global != None:
if not isinstance(max_mints_global, int) or max_mints_global < DFT_MINT_MAX_MIN_COUNT or max_mints_global > DFT_MINT_MAX_MAX_COUNT_DENSITY:
logger.warning(f'DFT init has invalid maxg {hash_to_hex_str(tx_hash)}, {max_mints_global}. Skipping...')
return None, None
mint_info['$max_mints_global'] = max_mints_global
else:
mint_info['$mint_mode'] = 'fixed'

Expand Down
40 changes: 29 additions & 11 deletions electrumx/server/block_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1456,8 +1456,11 @@ def create_or_delete_atomical(self, operations_found_at_inputs, atomicals_spent_
# Add $max_supply informative property
if mint_info['subtype'] == 'decentralized':
# For perpetual mints the max supply is unbounded
if mint_info.get('$mint_mode') == 'infinite':
mint_info['$max_supply'] = -1
if mint_info.get('$mint_mode') == 'perpetual':
if mint_info.get('$max_mints_global'):
mint_info['$max_supply'] = mint_info['$mint_amount'] * mint_info.get('$max_mints_global')
else:
mint_info['$max_supply'] = -1
else:
mint_info['$max_supply'] = mint_info['$mint_amount'] * mint_info['$max_mints']
else:
Expand Down Expand Up @@ -1983,7 +1986,7 @@ async def get_dft_mint_info_rpc_format_by_atomical_id(self, atomical_id):
}
mint_count = self.get_distmints_count_by_atomical_id(self.height, atomical_id, True)
atomical_result['dft_info']['mint_count'] = mint_count
if atomical_result.get('$mint_mode') == 'infinite':
if atomical_result.get('$mint_mode') == 'perpetual':
self.logger.debug(f'atomical_result={atomical_result}')
mint_bitwork_vec = atomical_result.get('$mint_bitwork_vec')
mint_bitworkc_inc = atomical_result.get('$mint_bitworkc_inc')
Expand Down Expand Up @@ -2161,13 +2164,14 @@ def get_base_mint_info_by_atomical_id(self, atomical_id):
# The mint mode can be fixed with a known max_supply
# Or the mode mint can be perpetual with an unbounded max_supply
atomical['$mint_mode'] = init_mint_info.get('$mint_mode') or 'fixed'
if init_mint_info.get('$mint_mode') == 'infinite':
atomical['$max_supply'] = -1
if init_mint_info.get('$mint_mode') == 'perpetual':
atomical['$max_supply'] = init_mint_info['$max_supply']
atomical['$mint_bitwork_vec'] = init_mint_info['$mint_bitwork_vec']
atomical['$mint_bitworkc_inc'] = init_mint_info.get('$mint_bitworkc_inc')
atomical['$mint_bitworkc_start'] = init_mint_info.get('$mint_bitworkc_start')
atomical['$mint_bitworkr_inc'] = init_mint_info.get('$mint_bitworkr_inc')
atomical['$mint_bitworkr_start'] = init_mint_info.get('$mint_bitworkr_start')
atomical['$max_mints_global'] = init_mint_info.get('$max_mints_global')
else:
atomical['$max_supply'] = init_mint_info['$max_supply']

Expand Down Expand Up @@ -2547,11 +2551,21 @@ def create_or_delete_decentralized_mint_output(self, atomicals_operations_found_
if mint_amount == txout.value:
# Count the number of existing b'gi' entries and ensure it is strictly less than max_mints
decentralized_mints = self.get_distmints_count_by_atomical_id(height, dmt_mint_atomical_id, True)
# Assess whether we allow the mint based on 'fixed' or 'infinite' mint modes
# Assess whether we allow the mint based on 'fixed' or 'perpetual' mint modes
# The perpetual mint mode will derive the minimum expected bitworkr/c needed given the quantity of already minted units
allow_mint = False
if mint_mode == 'infinite':
# In the 'infinite' mint mode an unbounded number of tokens can be minted according to the ever increasing bitworkc/r
if mint_mode == 'perpetual':
# If the perpetual token as a global max, then validate
max_mints_global = mint_info_for_ticker.get('$max_mints_global')
if max_mints_global:
if decentralized_mints > max_mints_global:
raise IndexError(f'create_or_delete_decentralized_mint_outputs: Fatal IndexError decentralized_mints > max_mints_global for {location_id_bytes_to_compact(dmt_mint_atomical_id)}. Too many mints detected in db')
if decentralized_mints == max_mints_global:
self.logger.debug(f'create_or_delete_decentralized_mint_outputs found invalid mint infinit operation because it is minted out completely due to global max mints. {hash_to_hex_str(tx_hash)}. Ignoring...')
return None

self.logger.debug(f'create_or_delete_decentralized_mint_outputs: found perpetual mint request in {hash_to_hex_str(tx_hash)} for {ticker}. Checking for any POW in distributed mint record...')
# In the 'perpetual' mint mode an unbounded number of tokens can be minted according to the ever increasing bitworkc/r
mint_bitwork_vec = mint_info_for_ticker.get('$mint_bitwork_vec')
mint_bitworkc_inc = mint_info_for_ticker.get('$mint_bitworkc_inc')
mint_bitworkr_inc = mint_info_for_ticker.get('$mint_bitworkr_inc')
Expand All @@ -2569,7 +2583,8 @@ def create_or_delete_decentralized_mint_output(self, atomicals_operations_found_
expected_minimum_bitworkr = calculate_expected_bitwork(mint_bitwork_vec, decentralized_mints, max_mints, mint_bitworkr_inc, mint_bitworkr_start)
if not is_mint_pow_valid(atomicals_operations_found_at_inputs['reveal_location_txid'], expected_minimum_bitworkr):
self.logger.warning(f'create_or_delete_decentralized_mint_output: mint_bitworkr_inc not is_mint_pow_valid {hash_to_hex_str(tx_hash)}, expected_minimum_bitworkr={expected_minimum_bitworkr}, atomicals_operations_found_at_inputs={atomicals_operations_found_at_inputs}...')
return None
return None

allow_mint = True
else:
# It is the 'fixed' mint mode and the bitworkc/r is static
Expand Down Expand Up @@ -2858,8 +2873,11 @@ def validate_no_dft_inflation(self, atomical_id_map, height):
mint_info_for_ticker = self.get_atomicals_id_mint_info(atomical_id_of_dft_ticker, False)
max_mints = mint_info_for_ticker['$max_mints']
dft_mode = mint_info_for_ticker.get('$mint_mode')
if dft_mode == 'infinite':
continue
# If it's mining mode, then use the max_mints_global if it's set
if dft_mode == 'perpetual':
if not mint_info_for_ticker.get('$max_mints_global'):
continue
max_mints = mint_info_for_ticker.get('$max_mints_global')
# Count the number of existing b'gi' entries and ensure it is strictly less than max_mints
decentralized_mints = self.get_distmints_count_by_atomical_id(height, atomical_id_of_dft_ticker, False)
if decentralized_mints > max_mints:
Expand Down

0 comments on commit f2f0b4d

Please sign in to comment.