From 25f265cd433e4c63efb4d52c767c8c4d07f4502f Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 23 Feb 2024 01:49:40 -0800 Subject: [PATCH 01/42] cleanup ledger hash generation - removed balances hash - updated sanity checks to only do checks on active ACTIONS - created getBlockTableHashes() function - created getBlockHashes() function --- indexer/includes/functions.php | 208 ++++++++++++++++++--------------- indexer/sql/blocks.sql | 2 - 2 files changed, 117 insertions(+), 93 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 6d2b135..4207f8b 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -648,10 +648,6 @@ function createDebit( $action=null, $block_index=null, $event=null, $tick=null, // Create record in `blocks` table function createBlock( $block=null ){ global $mysqli, $dbase; - $credits = array(); - $debits = array(); - $balances = array(); - $transactions = array(); $block_time = 0; // Get timestamp of Block from main database $results = $mysqli->query("SELECT block_time FROM {$dbase}.blocks WHERE block_index='{$block}' LIMIT 1"); @@ -663,62 +659,11 @@ function createBlock( $block=null ){ } else { byeLog('Error while trying to lookup records in credits table'); } - - // Get all data from credits table - $results = $mysqli->query("SELECT * FROM credits WHERE block_index<='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); - if($results){ - if($results->num_rows){ - while($row = $results->fetch_assoc()) - array_push($credits, (object) $row); - } - } else { - byeLog('Error while trying to lookup records in credits table'); - } - // Get all data from debits table - $results = $mysqli->query("SELECT * FROM debits WHERE block_index<='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); - if($results){ - if($results->num_rows){ - while($row = $results->fetch_assoc()) - array_push($debits, (object) $row); - } - } else { - byeLog('Error while trying to lookup records in debits table'); - } - // Get all data from balances table - $results = $mysqli->query("SELECT * FROM balances WHERE id IS NOT NULL ORDER BY tick_id ASC, address_id ASC, amount DESC"); - if($results){ - if($results->num_rows){ - while($row = $results->fetch_assoc()) - array_push($balances, (object) $row); - } - } else { - byeLog('Error while trying to lookup records in balances table'); - } - // Get all data from transactions table - $results = $mysqli->query("SELECT * FROM transactions WHERE tx_index IS NOT NULL ORDER BY tx_index ASC"); - if($results){ - if($results->num_rows){ - while($row = $results->fetch_assoc()) - array_push($transactions, (object) $row); - } - } else { - byeLog('Error while trying to lookup records in balances table'); - } - // Generate SHA256 hashes based on the json object - // This is a rough/dirty way to get some sha256 hashes qucikly... def should revisit when not in a rush - $credits_hash = hash('sha256', json_encode($credits)); - $debits_hash = hash('sha256', json_encode($debits)); - $balances_hash = hash('sha256', json_encode($balances)); - $transactions_hash = hash('sha256', json_encode($transactions)); - $credits_hash_short = substr($credits_hash,0,5); - $debits_hash_short = substr($debits_hash,0,5); - $balances_hash_short = substr($balances_hash,0,5); - $transactions_hash_short = substr($transactions_hash,0,5); - $credits_hash_id = createTransaction($credits_hash); - $debits_hash_id = createTransaction($debits_hash); - $balances_hash_id = createTransaction($balances_hash); - $txlist_hash_id = createTransaction($transactions_hash); - print "\n\t [credits:{$credits_hash_short} debits:{$debits_hash_short} balances:{$balances_hash_short} txlist:{$transactions_hash_short}]"; + // Get a list of hashes for this block + list($credits, $debits, $txlist) = getBlockHashes($block); + $credits_hash_id = createTransaction($credits); + $debits_hash_id = createTransaction($debits); + $txlist_hash_id = createTransaction($txlist); // Check if record already exists $results = $mysqli->query("SELECT id FROM blocks WHERE block_index='{$block}'"); if($results){ @@ -730,13 +675,12 @@ function createBlock( $block=null ){ block_time='{$block_time}', credits_hash_id='{$credits_hash_id}', debits_hash_id='{$debits_hash_id}', - balances_hash_id='{$balances_hash_id}', txlist_hash_id='{$txlist_hash_id}' WHERE block_index='{$block}'"; } else { // INSERT record - $sql = "INSERT INTO blocks (block_index, block_time, credits_hash_id, debits_hash_id, balances_hash_id, txlist_hash_id) values ('{$block}', '{$block_time}', '{$credits_hash_id}', '{$debits_hash_id}', '{$balances_hash_id}', '{$txlist_hash_id}')"; + $sql = "INSERT INTO blocks (block_index, block_time, credits_hash_id, debits_hash_id, txlist_hash_id) values ('{$block}', '{$block_time}', '{$credits_hash_id}', '{$debits_hash_id}', '{$txlist_hash_id}')"; } $results = $mysqli->query($sql); if(!$results) @@ -744,6 +688,12 @@ function createBlock( $block=null ){ } else { byeLog('Error while trying to lookup record in blocks table'); } + // Print out a status update + $credits = substr($credits,0,5); + $debits = substr($debits,0,5); + $txlist = substr($txlist,0,5); + print "\n\t [credits:{$credits} debits:{$debits} txlist:{$txlist}]"; + } // Create record in `lists` table @@ -1700,7 +1650,7 @@ function isActionAllowed($tick=null, $address=null){ // Validate that token supplys match credits/debits/balances information function sanityCheck( $block=null ){ - global $mysqli; + global $mysqli, $network; $tickers = []; // Assoc array of tickers $supply = []; // Assoc array of supplys $block_index = $mysqli->real_escape_string($block); @@ -1719,35 +1669,39 @@ function sanityCheck( $block=null ){ if($results->num_rows){ while($row = $results->fetch_assoc()){ $row = (object) $row; - // Ignore certain tx types - if(in_array($row->type,array('LIST'))) - continue; - // Loop through tables and get ticker and supply - $table = strtolower($row->type) . 's'; - $sql = "SELECT - t2.id, - t2.tick, - t1.supply - FROM - {$table} m LEFT JOIN tokens t1 on (t1.tick_id=m.tick_id), - index_tickers t2 - WHERE - t2.id=m.tick_id AND - m.block_index='{$block_index}'"; - // print $sql; - $results2 = $mysqli->query($sql); - if($results2){ - if($results2->num_rows){ - while($row2 = $results2->fetch_assoc()){ - $row2 = (object) $row2; - // Add ticker and supply info to assoc arrays - $tickers[$row2->tick] = $row2->id; - $supply[$row2->tick] = (!is_null($row2->supply)) ? $row2->supply : "0"; + // Only perform sanity checks on ACTIONS that are active in protocol_changes + if(isEnabled($row->type, $network, $block)){ + // Ignore certain tx types + if(in_array($row->type,array('LIST'))) + continue; + // Loop through tables and get ticker and supply + $table = strtolower($row->type) . 's'; + $sql = "SELECT + t2.id, + t2.tick, + t1.supply + FROM + {$table} m LEFT JOIN tokens t1 on (t1.tick_id=m.tick_id), + index_tickers t2 + WHERE + t2.id=m.tick_id AND + m.block_index='{$block_index}'"; + // print $sql; + $results2 = $mysqli->query($sql); + if($results2){ + if($results2->num_rows){ + while($row2 = $results2->fetch_assoc()){ + $row2 = (object) $row2; + // Add ticker and supply info to assoc arrays + $tickers[$row2->tick] = $row2->id; + $supply[$row2->tick] = (!is_null($row2->supply)) ? $row2->supply : "0"; + } } - } - } else { - byeLog("Error while trying to lookup tickers in block : {$block}"); + } else { + byeLog("Error while trying to lookup tickers in block : {$block}"); + } } + } } } else { @@ -1797,4 +1751,76 @@ function getActionCreditDebitAmount($table=null, $action=null, $tick=null, $addr $total = $data[$tick_id]; return $total; } -?> \ No newline at end of file + +// Get block hashes using credits/debits/transactions table data +function getBlockHashes($block=null){ + global $mysqli; + $credits = array(); + $debits = array(); + $txlist = array(); + // Get all block data from credits table + $results = $mysqli->query("SELECT * FROM credits WHERE block_index<='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()) + array_push($credits, (object) $row); + } + } else { + byeLog('Error while trying to lookup records in credits table'); + } + // Get all block data from debits table + $results = $mysqli->query("SELECT * FROM debits WHERE block_index<='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()) + array_push($debits, (object) $row); + } + } else { + byeLog('Error while trying to lookup records in debits table'); + } + // Get all block data from transactions table + $results = $mysqli->query("SELECT * FROM transactions WHERE block_index<='{$block}' ORDER BY tx_index ASC"); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()) + array_push($txlist, (object) $row); + } + } else { + byeLog('Error while trying to lookup records in transactions table'); + } + // Generate SHA256 hashes based on the json object + $credits = hash('sha256', json_encode($credits)); + $debits = hash('sha256', json_encode($debits)); + $txlist = hash('sha256', json_encode($txlist)); + return array($credits, $debits, $txlist); +} + +// Get block hashes using blocks table data +function getBlockTableHashes($block=null){ + global $mysqli; + $hashes = false; + $sql = "SELECT + t1.hash as credits, + t2.hash as debits, + t3.hash as txlist + FROM + blocks b, + index_transactions t1, + index_transactions t2, + index_transactions t3 + WHERE + t1.id=b.credits_hash_id AND + t2.id=b.debits_hash_id AND + t3.id=b.txlist_hash_id AND + b.block_index='{$block}'"; + $results = $mysqli->query($sql); + if($results && $results->num_rows){ + $row = (object) $results->fetch_assoc(); + $hashes = array($row->credits,$row->debits, $row->txlist); + } else { + byeLog("Error while trying to lookup block hashes"); + } + return $hashes; +} + +?> diff --git a/indexer/sql/blocks.sql b/indexer/sql/blocks.sql index 07655b0..4cf6ffb 100644 --- a/indexer/sql/blocks.sql +++ b/indexer/sql/blocks.sql @@ -5,11 +5,9 @@ CREATE TABLE blocks ( block_time INTEGER UNSIGNED, credits_hash_id INTEGER UNSIGNED, -- id of record in index_transactions table (sha256 hash of credits data) debits_hash_id INTEGER UNSIGNED, -- id of record in index_transactions table (sha256 hash of debits data) - balances_hash_id INTEGER UNSIGNED, -- id of record in index_transactions table (sha256 hash of balances data) txlist_hash_id INTEGER UNSIGNED -- id of record in index_transactions table (sha256 hash of index_tx data) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE INDEX block_index ON blocks (block_index); CREATE INDEX credits_hash_id ON blocks (credits_hash_id); CREATE INDEX debits_hash_id ON blocks (debits_hash_id); -CREATE INDEX balances_hash_id ON blocks (balances_hash_id); From f4992d5314ebf3ca29fa9e7d4839384506d5e21e Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 23 Feb 2024 08:54:39 -0800 Subject: [PATCH 02/42] todo `updateBalances()` optimization --- indexer/includes/actions/send.php | 1 + 1 file changed, 1 insertion(+) diff --git a/indexer/includes/actions/send.php b/indexer/includes/actions/send.php index 615c7c6..d79f869 100644 --- a/indexer/includes/actions/send.php +++ b/indexer/includes/actions/send.php @@ -208,6 +208,7 @@ function btnsSend($params=null, $data=null, $error=null){ } // Update address balances + // TODO: Optimize this to only update balances for ticks, not full balances... its way too slow now updateBalances(array_keys($addresses)); } From 42a35a7ffcda21be823ac36c88c73c0ea0bd184f Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 23 Feb 2024 09:48:04 -0800 Subject: [PATCH 03/42] created `processTransaction()` function --- indexer/includes/functions.php | 68 +++++++++++++++++++++++++++++++++ indexer/indexer.php | 69 +++------------------------------- 2 files changed, 74 insertions(+), 63 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 4207f8b..60c5da8 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1823,4 +1823,72 @@ function getBlockTableHashes($block=null){ return $hashes; } +// Generalized function to handle processing a broadcast transaction +// @param {tx} object Transaction object +// @param {tx->source} string Source address +// @param {$tx->text} string Broadcast `text` +// @param {$tx->version} integer Broadcast `value` +// @param {$tx->tx_hash} string Transaction hash +// @param {$tx->block_index} string Block index of tx +function processTransaction($tx=null){ + // Assoc arrays to track address/ticker changes + $addresses = array(); + $tickers = array(); + $error = false; + $tx = (object) $tx; + $prefixes = array('/^bt:/','/^btns:/'); + $params = explode('|',preg_replace($prefixes,'',$tx->text)); + $version = $tx->version; // Project Version + $source = $tx->source; // Source address + + // Create database records and get ids for tx_hash and source address + $source_id = createAddress($tx->source); + $tx_hash_id = createTransaction($tx->tx_hash); + + // Trim whitespace from any PARAMS + foreach($params as $idx => $value) + $params[$idx] = trim($value); + + // Extract ACTION from PARAMS + $action = strtoupper(array_shift($params)); + + // Support legacy BTNS format with no VERSION on DEPLOY/MINT/TRANSFER actions (default to VERSION 0) + if(in_array($action,array('DEPLOY','MINT','TRANSFER')) && isLegacyBTNSFormat($params)) + array_splice($params, 0, 0, 0); + + // Support old BRC20/SRC20 actions + if($action=='TRANSFER') $action = 'SEND'; + if($action=='DEPLOY') $action = 'ISSUE'; + + // Define basic BTNS transaction data object + $data = (object) array( + 'ACTION' => $action, // Action (ISSUE, MINT, SEND, etc) + 'BLOCK_INDEX' => $tx->block_index, // Block index + 'SOURCE' => $tx->source, // Source/Broadcasting address + 'TX_HASH' => $tx->tx_hash // Transaction Hash + ); + + // Validate Action + if(!array_key_exists($action,PROTOCOL_CHANGES)) + $error = 'invalid: Unknown ACTION'; + + // Verify action is activated (past ACTIVATION_BLOCK) + if(!$error && !isEnabled($action, $network, $block)) + $error = 'invalid: ACTIVATION_BLOCK'; + + // Set action to UNKNOWN if we detect error + if($error) + $data->ACTION = $action = 'UNKNOWN'; + + // Create a record of this transaction in the transactions table + createTxIndex($data); + + // Get tx_index of record using tx_hash + $data->TX_INDEX = getTxIndex($data->TX_HASH); + + // Handle processing the specific BTNS ACTION commands + btnsAction($action, $params, $data, $error); +} + + ?> diff --git a/indexer/indexer.php b/indexer/indexer.php index b9b1ba4..3118def 100755 --- a/indexer/indexer.php +++ b/indexer/indexer.php @@ -95,7 +95,8 @@ b.text, b.value as version, t.hash as tx_hash, - a.address as source + a.address as source, + b.block_index as block_index FROM {$dbase}.broadcasts b, {$dbase}.index_transactions t, @@ -109,72 +110,14 @@ ORDER BY b.tx_index ASC"; $results = $mysqli->query($sql); if($results){ - if($results->num_rows){ - while($row = $results->fetch_assoc()){ - // Assoc arrays to track address/ticker changes - $addresses = array(); - $tickers = array(); - $error = false; - $row = (object) $row; - $prefixes = array('/^bt:/','/^btns:/'); - $params = explode('|',preg_replace($prefixes,'',$row->text)); - $version = $row->version; // Project Version - $source = $row->source; // Source address - - // Create database records and get ids for tx_hash and source address - $source_id = createAddress($row->source); - $tx_hash_id = createTransaction($row->tx_hash); - - // Trim whitespace from any PARAMS - foreach($params as $idx => $value) - $params[$idx] = trim($value); - - // Extract ACTION from PARAMS - $action = strtoupper(array_shift($params)); - - // Support legacy BTNS format with no VERSION on DEPLOY/MINT/TRANSFER actions (default to VERSION 0) - if(in_array($action,array('DEPLOY','MINT','TRANSFER')) && isLegacyBTNSFormat($params)) - array_splice($params, 0, 0, 0); - - // Support old BRC20/SRC20 actions - if($action=='TRANSFER') $action = 'SEND'; - if($action=='DEPLOY') $action = 'ISSUE'; - - // Define basic BTNS transaction data object - $data = (object) array( - 'ACTION' => $action, // Action (ISSUE, MINT, SEND, etc) - 'BLOCK_INDEX' => $block, // Block index - 'SOURCE' => $row->source, // Source/Broadcasting address - 'TX_HASH' => $row->tx_hash // Transaction Hash - ); - - // Validate Action - if(!array_key_exists($action,PROTOCOL_CHANGES)) - $error = 'invalid: Unknown ACTION'; - - // Verify action is activated (past ACTIVATION_BLOCK) - if(!$error && !isEnabled($action, $network, $block)) - $error = 'invalid: ACTIVATION_BLOCK'; - - // Set action to UNKNOWN if we detect error - if($error) - $data->ACTION = $action = 'UNKNOWN'; - - // Create a record of this transaction in the transactions table - createTxIndex($data); - - // Get tx_index of record using tx_hash - $data->TX_INDEX = getTxIndex($data->TX_HASH); - - // Handle processing the specific BTNS ACTION commands - btnsAction($action, $params, $data, $error); - } - } + if($results->num_rows) + while($row = $results->fetch_assoc()) + processTransaction($row); } else { byeLog("Error while trying to lookup BTNS broadcasts"); } - // Create hash of the credits/debits/balances table and create record in `blocks` table + // Create record in `blocks` table with hashes of the credits/debits/transactions tables createBlock($block); // Do a sanity check to verify that token supplys match data in credits/debits/balances tables From 117f5dc8eacd81e6acc8e841d39a5b7905a7da56 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 23 Feb 2024 10:11:48 -0800 Subject: [PATCH 04/42] todo `getAddressBalances()` optimization --- indexer/includes/actions/send.php | 1 + 1 file changed, 1 insertion(+) diff --git a/indexer/includes/actions/send.php b/indexer/includes/actions/send.php index d79f869..f881f32 100644 --- a/indexer/includes/actions/send.php +++ b/indexer/includes/actions/send.php @@ -88,6 +88,7 @@ function btnsSend($params=null, $data=null, $error=null){ } // Get source address balances + // TODO : add block index to get balances as of block X $balances = getAddressBalances($data->SOURCE); // Store original error value From 518c1a8995325ee53afa5e3b169da3372046e8b4 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 23 Feb 2024 11:56:51 -0800 Subject: [PATCH 05/42] created `getBroadcastTransactions()` function --- indexer/includes/functions.php | 33 +++++++++++++++++++++++++++++++++ indexer/indexer.php | 30 ++++-------------------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 60c5da8..7261262 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1890,5 +1890,38 @@ function processTransaction($tx=null){ btnsAction($action, $params, $data, $error); } +// Get broadcast transactions for a given block +function getBroadcastTransactions($block){ + global $mysqli, $dbase; + $data = array(); + // Lookup any BTNS action broadcasts in this block (anything with bt: or btns: prefix) + $sql = "SELECT + b.text, + b.value as version, + t.hash as tx_hash, + a.address as source, + b.block_index as block_index + FROM + {$dbase}.broadcasts b, + {$dbase}.index_transactions t, + {$dbase}.index_addresses a + WHERE + t.id=b.tx_hash_id AND + a.id=b.source_id AND + b.block_index='{$block}' AND + b.status='valid' AND + (b.text LIKE 'bt:%' OR b.text LIKE 'btns:%') + ORDER BY b.tx_index ASC"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows) + while($row = $results->fetch_assoc()) + array_push($data, $row); + } else { + byeLog("Error while trying to lookup BTNS broadcasts"); + } + return $data; +} + ?> diff --git a/indexer/indexer.php b/indexer/indexer.php index 3118def..3013c6b 100755 --- a/indexer/indexer.php +++ b/indexer/indexer.php @@ -90,32 +90,10 @@ $timer = new Profiler(); print "processing block {$block}..."; - // Lookup any BTNS action broadcasts in this block (anything with bt: or btns: prefix) - $sql = "SELECT - b.text, - b.value as version, - t.hash as tx_hash, - a.address as source, - b.block_index as block_index - FROM - {$dbase}.broadcasts b, - {$dbase}.index_transactions t, - {$dbase}.index_addresses a - WHERE - t.id=b.tx_hash_id AND - a.id=b.source_id AND - b.block_index='{$block}' AND - b.status='valid' AND - (b.text LIKE 'bt:%' OR b.text LIKE 'btns:%') - ORDER BY b.tx_index ASC"; - $results = $mysqli->query($sql); - if($results){ - if($results->num_rows) - while($row = $results->fetch_assoc()) - processTransaction($row); - } else { - byeLog("Error while trying to lookup BTNS broadcasts"); - } + // Get any broadcast transactions for this block and process them + $txs = getBroadcastTransactions($block); + foreach($txs as $tx) + processTransaction($tx); // Create record in `blocks` table with hashes of the credits/debits/transactions tables createBlock($block); From a2f5858c3de9112fae2bf6ce4131dc0e1285a3cc Mon Sep 17 00:00:00 2001 From: J-Dog Date: Mon, 26 Feb 2024 15:26:55 -0800 Subject: [PATCH 06/42] fix issue where block_index is being updated --- indexer/includes/functions.php | 1 - 1 file changed, 1 deletion(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 7261262..079dc3d 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -530,7 +530,6 @@ function createToken( $data=null ){ mint_address_max='{$mint_address_max}', mint_start_block='{$mint_start_block}', mint_stop_block='{$mint_stop_block}', - block_index='{$block_index}', supply='{$supply}', owner_id='{$owner_id}' WHERE From 707d060ebe9e26e2d5c85e5c1a59f4fcc3f0457f Mon Sep 17 00:00:00 2001 From: J-Dog Date: Tue, 27 Feb 2024 18:30:55 -0800 Subject: [PATCH 07/42] =?UTF-8?q?add=20`=E2=80=94reparse`=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - added `reparse` functionality to allow quick reparsing and validation of the ledger transactions --- indexer/includes/actions/airdrop.php | 2 +- indexer/includes/actions/batch.php | 2 +- indexer/includes/actions/bet.php | 2 +- indexer/includes/actions/callback.php | 2 +- indexer/includes/actions/destroy.php | 2 +- indexer/includes/actions/dispenser.php | 2 +- indexer/includes/actions/dividend.php | 2 +- indexer/includes/actions/issue.php | 6 +- indexer/includes/actions/list.php | 2 +- indexer/includes/actions/mint.php | 6 +- indexer/includes/actions/rug.php | 2 +- indexer/includes/actions/send.php | 6 +- indexer/includes/actions/sleep.php | 2 +- indexer/includes/actions/sweep.php | 2 +- indexer/includes/config.php | 3 + indexer/includes/functions.php | 152 ++++++++++++++++++------- indexer/includes/reparse.php | 85 ++++++++++++++ indexer/indexer.php | 8 +- 18 files changed, 229 insertions(+), 59 deletions(-) create mode 100644 indexer/includes/reparse.php diff --git a/indexer/includes/actions/airdrop.php b/indexer/includes/actions/airdrop.php index 61968fd..4cd83cb 100644 --- a/indexer/includes/actions/airdrop.php +++ b/indexer/includes/actions/airdrop.php @@ -13,7 +13,7 @@ * 1 = VERSION|TICK|AMOUNT|LIST|TICK|AMOUNT|LIST ********************************************************************/ function btnsAirdrop($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/batch.php b/indexer/includes/actions/batch.php index 61a2684..7883748 100644 --- a/indexer/includes/actions/batch.php +++ b/indexer/includes/actions/batch.php @@ -10,7 +10,7 @@ * 0 = VERSION|COMMAND;COMMAND ********************************************************************/ function btnsBatch($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/bet.php b/indexer/includes/actions/bet.php index 68b495d..2d8ec01 100644 --- a/indexer/includes/actions/bet.php +++ b/indexer/includes/actions/bet.php @@ -19,7 +19,7 @@ * 0 = VERSION|FEED_ADDRESS|BET_TYPE|DEADLINE|WAGER_TICK|WAGER_AMOUNT|COUNTERWAGER_TICK|COUNTERWAGER_AMOUNT|EXPIRATION|LEVERAGE|TARGET_VALUE ********************************************************************/ function btnsBet($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/callback.php b/indexer/includes/actions/callback.php index ae63d50..37e6248 100644 --- a/indexer/includes/actions/callback.php +++ b/indexer/includes/actions/callback.php @@ -10,7 +10,7 @@ * 0 = VERSION|TICK ********************************************************************/ function btnsCallback($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/destroy.php b/indexer/includes/actions/destroy.php index 41ea966..f819b3f 100644 --- a/indexer/includes/actions/destroy.php +++ b/indexer/includes/actions/destroy.php @@ -15,7 +15,7 @@ * ********************************************************************/ function btnsDestroy($params=null, $data=null, $error=null){ - global $mysqli, $tickers, $addresses; + global $mysqli, $reparse, $tickers, $addresses; // Define list of known FORMATS $formats = array( diff --git a/indexer/includes/actions/dispenser.php b/indexer/includes/actions/dispenser.php index 95f75b3..0d7f60b 100644 --- a/indexer/includes/actions/dispenser.php +++ b/indexer/includes/actions/dispenser.php @@ -19,7 +19,7 @@ * 0 = VERSION|GIVE_TICK|GIVE_AMOUNT|ESCROW_AMOUNT|TRIGGER_TICK|TRIGGER_AMOUNT|STATUS|ADDRESS|ORACLE_ADDRESS|ALLOW_LIST|BLOCK_LIST ********************************************************************/ function btnsDispenser($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/dividend.php b/indexer/includes/actions/dividend.php index 94ee133..fd41113 100644 --- a/indexer/includes/actions/dividend.php +++ b/indexer/includes/actions/dividend.php @@ -12,7 +12,7 @@ * 0 = VERSION|TICK|DIVIDEND_TICK|AMOUNT ********************************************************************/ function btnsDividend($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/issue.php b/indexer/includes/actions/issue.php index ed062aa..250ef1c 100644 --- a/indexer/includes/actions/issue.php +++ b/indexer/includes/actions/issue.php @@ -36,7 +36,7 @@ * ********************************************************************/ function btnsIssue( $params=null, $data=null, $error=null){ - global $mysqli, $tickers, $addresses; + global $mysqli, $reparse, $tickers, $addresses; // Define list of known FORMATS $formats = array( @@ -309,6 +309,10 @@ function btnsIssue( $params=null, $data=null, $error=null){ createCredit('ISSUE', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->MINT_SUPPLY, $data->TRANSFER_SUPPLY); } + // If this is a reparse, bail out before updating balances and token information + if($reparse) + return; + // Update balances for addresses updateBalances([$data->SOURCE, $data->TRANSFER_SUPPLY]); diff --git a/indexer/includes/actions/list.php b/indexer/includes/actions/list.php index fa95f92..d7f48ee 100644 --- a/indexer/includes/actions/list.php +++ b/indexer/includes/actions/list.php @@ -15,7 +15,7 @@ * ********************************************************************/ function btnsList( $params=null, $data=null, $error=null){ - global $mysqli, $tickers, $addresses; + global $mysqli, $reparse, $tickers, $addresses; // Define list of known FORMATS $formats = array( diff --git a/indexer/includes/actions/mint.php b/indexer/includes/actions/mint.php index 746fe1f..3a70a22 100644 --- a/indexer/includes/actions/mint.php +++ b/indexer/includes/actions/mint.php @@ -13,7 +13,7 @@ * ********************************************************************/ function btnsMint($params=null, $data=null, $error=null){ - global $mysqli, $tickers, $addresses; + global $mysqli, $reparse, $tickers, $addresses; // Define list of known FORMATS $formats = array( @@ -137,6 +137,10 @@ function btnsMint($params=null, $data=null, $error=null){ } } + // If this is a reparse, bail out before updating balances and token information + if($reparse) + return; + // Update balances for addresses updateBalances([$data->SOURCE, $data->DESTINATION]); diff --git a/indexer/includes/actions/rug.php b/indexer/includes/actions/rug.php index 4b36ea6..3e11274 100644 --- a/indexer/includes/actions/rug.php +++ b/indexer/includes/actions/rug.php @@ -10,7 +10,7 @@ * 0 = VERSION|TICK ********************************************************************/ function btnsRug($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/send.php b/indexer/includes/actions/send.php index f881f32..ae78ee5 100644 --- a/indexer/includes/actions/send.php +++ b/indexer/includes/actions/send.php @@ -17,7 +17,7 @@ * ********************************************************************/ function btnsSend($params=null, $data=null, $error=null){ - global $mysqli, $tickers, $addresses; + global $mysqli, $reparse, $tickers, $addresses; // Define list of known FORMATS $formats = array( @@ -208,6 +208,10 @@ function btnsSend($params=null, $data=null, $error=null){ createCredit('SEND', $data->BLOCK_INDEX, $data->TX_HASH, $tick, $amount, $destination); } + // If this is a reparse, bail out before updating balances + if($reparse) + return; + // Update address balances // TODO: Optimize this to only update balances for ticks, not full balances... its way too slow now updateBalances(array_keys($addresses)); diff --git a/indexer/includes/actions/sleep.php b/indexer/includes/actions/sleep.php index 515efdf..96c173a 100644 --- a/indexer/includes/actions/sleep.php +++ b/indexer/includes/actions/sleep.php @@ -11,7 +11,7 @@ * 0 = VERSION|TICK|RESUME_BLOCK ********************************************************************/ function btnsSleep($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/actions/sweep.php b/indexer/includes/actions/sweep.php index 4008d28..959aa15 100644 --- a/indexer/includes/actions/sweep.php +++ b/indexer/includes/actions/sweep.php @@ -13,7 +13,7 @@ * 0 = VERSION|DESTINATION|SWEEP_BALANCES|SWEEP_OWNERSHIP|MEMO ********************************************************************/ function btnsSweep($params=null, $data=null, $error=null){ - global $mysqli; + global $mysqli, $reparse; // Coming soon } diff --git a/indexer/includes/config.php b/indexer/includes/config.php index 0ed44e7..3433041 100644 --- a/indexer/includes/config.php +++ b/indexer/includes/config.php @@ -64,6 +64,9 @@ // Rollback code require_once('rollback.php'); +// Reparse code +require_once('reparse.php'); + // Protocol Changes / Activation blocks require_once('protocol_changes.php'); diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 079dc3d..8154e93 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -659,10 +659,10 @@ function createBlock( $block=null ){ byeLog('Error while trying to lookup records in credits table'); } // Get a list of hashes for this block - list($credits, $debits, $txlist) = getBlockHashes($block); - $credits_hash_id = createTransaction($credits); - $debits_hash_id = createTransaction($debits); - $txlist_hash_id = createTransaction($txlist); + $info = getBlockHashes($block); + $credits_hash_id = createTransaction($info['credits']['hash']); + $debits_hash_id = createTransaction($info['debits']['hash']); + $txlist_hash_id = createTransaction($info['txlist']['hash']); // Check if record already exists $results = $mysqli->query("SELECT id FROM blocks WHERE block_index='{$block}'"); if($results){ @@ -864,7 +864,7 @@ function deleteLists($list=null, $rollback=null){ // Handle getting token information for a given tick -function getTokenInfo($tick=null, $tick_id=null){ +function getTokenInfo($tick=null, $tick_id=null, $block_index=null){ global $mysqli; $data = false; if(!is_null($tick) && is_null($tick_id)) @@ -904,7 +904,10 @@ function getTokenInfo($tick=null, $tick_id=null){ t2.id=t1.tick_id AND a.id=t1.owner_id AND t1.tick_id='{$tick_id}'"; - // print $sql; + // If a block index was given, only lookup token information before given block + if(isset($block_index) && is_numeric($block_index)) + $sql .= " AND t1.block_index <= {$block_index}"; + // print $sql; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ @@ -1031,7 +1034,7 @@ function getTokenDecimalPrecision($tick_id=null){ } // Handle getting credits or debits records for a given address -function getAddressCreditDebit($table=null, $address=null, $action=null){ +function getAddressCreditDebit($table=null, $address=null, $action=null, $block=null){ global $mysqli; $data = array(); // Assoc array to store tick/credits $type = gettype($address); @@ -1055,6 +1058,8 @@ function getAddressCreditDebit($table=null, $address=null, $action=null){ t1.address_id='{$address_id}'"; if(isset($action)) $sql .= " AND t1.action_id={$action_id}"; + if(isset($block) && is_numeric($block)) + $sql .= " AND t1.block_index < {$block}"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ @@ -1074,15 +1079,15 @@ function getAddressCreditDebit($table=null, $address=null, $action=null){ } // Get address balances using credits/debits table data -function getAddressBalances($address=null){ +function getAddressBalances($address=null, $tick=null, $block=null){ global $mysqli; $type = gettype($address); if($type==='integer' || is_numeric($address)) $address_id = $address; if($type==='string' && !is_numeric($address)) $address_id = createAddress($address); - $credits = getAddressCreditDebit('credits', $address_id); - $debits = getAddressCreditDebit('debits', $address_id); + $credits = getAddressCreditDebit('credits', $address_id, null, $block); + $debits = getAddressCreditDebit('debits', $address_id, null, $block); $decimals = array(); // Assoc array to store tick/decimals $balances = array(); // Assoc array to store tick/balance foreach($credits as $tick_id => $amount) @@ -1262,16 +1267,17 @@ function updateTokenInfo( $tick=null ){ } // Get token supply from credits/debits table (credits - debits = supply) -function getTokenSupply( $tick=null ){ +function getTokenSupply( $tick=null, $block_index=null ){ global $mysqli; $credits = 0; $debits = 0; $supply = 0; + $block = (is_numeric($block_index)) ? $block_index : 99999999999999; $tick_id = createTicker($tick); // Get info on decimal precision $decimals = getTokenDecimalPrecision($tick_id); // Get Credits - $sql = "SELECT CAST(SUM(amount) AS DECIMAL(60,$decimals)) as credits FROM credits WHERE tick_id='{$tick_id}'"; + $sql = "SELECT CAST(SUM(amount) AS DECIMAL(60,$decimals)) as credits FROM credits WHERE tick_id='{$tick_id}' AND block_index<='{$block}'"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ @@ -1282,7 +1288,7 @@ function getTokenSupply( $tick=null ){ byeLog('Error while trying to get list of credits'); } // Get Debits - $sql = "SELECT CAST(SUM(amount) AS DECIMAL(60,$decimals)) as debits FROM debits WHERE tick_id='{$tick_id}'"; + $sql = "SELECT CAST(SUM(amount) AS DECIMAL(60,$decimals)) as debits FROM debits WHERE tick_id='{$tick_id}' AND block_index<='{$block}'"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ @@ -1751,12 +1757,67 @@ function getActionCreditDebitAmount($table=null, $action=null, $tick=null, $addr return $total; } + + +// Get all data from a given table for a given block +function getBlockTableData($table=null, $block=null){ + global $mysqli; + $data = []; + // Get all block data from table + $results = $mysqli->query("SELECT tx_index, status_id FROM {$table} WHERE block_index='{$block}' ORDER BY tx_index ASC"); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()) + array_push($data, (object) $row); + } else { + array_push($data, (object) []); + } + } else { + byeLog("Error while trying to lookup records in {$table} table"); + } + return $data; +} + +// Function to get a SHA256 hash of a given data object +function getDataHash($data=null){ + $hash = hash('sha256', json_encode($data)); + return $hash; +} + +// Get block hashes using data from the ACTION tables +function getBlockDataHashes($block=null){ + global $mysqli; + // Define a list of tables + $tables = [ + 'destroys', + 'issues', + 'lists', + 'mints', + 'sends', + ]; + // Define response info object + $info = []; + // Loop through the data tables and dump a quick list of tx_index and status + foreach($tables as $table){ + $data = getBlockTableData($table, $block); + $hash = getDataHash($data); + $info[$table] = [ + 'hash' => $hash, + 'data' => $data + ]; + } + // Get hashes for data in the credits / debits / transactions tables + $info = array_merge($info, getBlockHashes($block)); + return $info; +} + // Get block hashes using credits/debits/transactions table data function getBlockHashes($block=null){ global $mysqli; $credits = array(); $debits = array(); $txlist = array(); + $info = array(); // Get all block data from credits table $results = $mysqli->query("SELECT * FROM credits WHERE block_index<='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); if($results){ @@ -1788,38 +1849,17 @@ function getBlockHashes($block=null){ byeLog('Error while trying to lookup records in transactions table'); } // Generate SHA256 hashes based on the json object - $credits = hash('sha256', json_encode($credits)); - $debits = hash('sha256', json_encode($debits)); - $txlist = hash('sha256', json_encode($txlist)); - return array($credits, $debits, $txlist); -} - -// Get block hashes using blocks table data -function getBlockTableHashes($block=null){ - global $mysqli; - $hashes = false; - $sql = "SELECT - t1.hash as credits, - t2.hash as debits, - t3.hash as txlist - FROM - blocks b, - index_transactions t1, - index_transactions t2, - index_transactions t3 - WHERE - t1.id=b.credits_hash_id AND - t2.id=b.debits_hash_id AND - t3.id=b.txlist_hash_id AND - b.block_index='{$block}'"; - $results = $mysqli->query($sql); - if($results && $results->num_rows){ - $row = (object) $results->fetch_assoc(); - $hashes = array($row->credits,$row->debits, $row->txlist); - } else { - byeLog("Error while trying to lookup block hashes"); + $tables = ['credits','debits','txlist']; + // Loop through the data tables and dump a quick list of tx_index and status + foreach($tables as $table){ + $data = ${$table}; + $hash = getDataHash($data); + // print "table={$table}\n"; + // print "hash={$hash}\n"; + // print "data=" . count($data) . "\n"; + $info[$table] = ['hash' => $hash]; } - return $hashes; + return $info; } // Generalized function to handle processing a broadcast transaction @@ -1922,5 +1962,29 @@ function getBroadcastTransactions($block){ return $data; } +// Get tx_index of the first valid ISSUE action for a given ticker +function getFirstIssuanceTxIndex($tick=null){ + global $mysqli; + $tick_id = createTicker($tick); + $sql = "SELECT tx_index FROM issues WHERE tick_id={$tick_id} AND status_id=1 ORDER BY tx_index ASC LIMIT 1"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + $row = (object) $results->fetch_assoc(); + return $row->tx_index; + } + } else { + byeLog("Error while trying to look up tx_index of first valid issuance"); + } + return false; +} + +// Handles validating if a ticker is valid before a given tx_index +function validTickerBeforeTxIndex($tick=null, $txIndex=null){ + $issueIndex = getFirstIssuanceTxIndex($tick); + if($issueIndex < $txIndex) + return true; + return false; +} ?> diff --git a/indexer/includes/reparse.php b/indexer/includes/reparse.php new file mode 100644 index 0000000..6c60102 --- /dev/null +++ b/indexer/includes/reparse.php @@ -0,0 +1,85 @@ + $info){ + if($ledgerA[$table]['hash']!=$ledgerB[$table]['hash']){ + $error .= " in the {$table} table"; + if(isset($ledgerA[$table]['data'])){ + foreach($ledgerA[$table]['data'] as $idx => $info){ + if($ledgerA[$table]['data'][$idx]!=$ledgerB[$table]['data'][$idx]){ + $tx_index = $ledgerA[$table]['data'][$idx]->tx_index; + if($tx_index) + $error .= " for tx_index {$tx_index}"; + } + } + } + } + } + } + + // Display any errors and exit + if($error){ + print "\n"; + byeLog($error); + } + + // Print out a status update + $credits = substr($ledgerA['credits']['hash'],0,5); + $debits = substr($ledgerA['debits']['hash'],0,5); + $txlist = substr($ledgerA['txlist']['hash'],0,5); + print "\n\t [credits:{$credits} debits:{$debits} txlist:{$txlist}]"; + + // Report time to process block + $time = $timer->finish(); + print " Done [{$time}sec]\n"; + + // Increase block before next loop + $block++; + } + + // Notify user of the total reparse time + print "Total Execution time: " . $runtime->finish() ." seconds\n"; + + // Notify user reparse is complete + byeLog("Reparse complete."); + +} + +?> diff --git a/indexer/indexer.php b/indexer/indexer.php index 3013c6b..cd0ab92 100755 --- a/indexer/indexer.php +++ b/indexer/indexer.php @@ -24,6 +24,7 @@ * --testnet Load data from testnet * --block=# Load data for given block * --rollback=# Rollback data to a given block + * --reparse Reparse and validate all transactions * --single Load single block ********************************************************************/ @@ -31,9 +32,10 @@ error_reporting(E_ERROR|E_PARSE); // Parse in any command line args and set basic runtime flags -$args = getopt("", array("testnet::", "block::", "single::", "rollback::",)); +$args = getopt("", array("testnet::", "block::", "single::", "rollback::", "reparse::")); $testnet = (isset($args['testnet'])) ? true : false; $single = (isset($args['single'])) ? true : false; +$reparse = (isset($args['reparse'])) ? true : false; $block = (is_numeric($args['block'])) ? intval($args['block']) : false; $network = ($testnet) ? 'testnet' : 'mainnet'; $rollback = (is_numeric($args['rollback'])) ? intval($args['rollback']) : false; @@ -85,6 +87,10 @@ if(file_exists($lockfile)) byeLog("found {$service} parsing a block... exiting"); +// Handle reparses +if($reparse) + btnsReparse($current); + // Loop through the blocks until we are current while($block <= $current){ $timer = new Profiler(); From e1f4597f087a5407eba8b4373ee826699043afc0 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 1 Mar 2024 12:08:44 -0800 Subject: [PATCH 08/42] =?UTF-8?q?support=20`=E2=80=94reparse=3D#`=20=20for?= =?UTF-8?q?mat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add support for reparsing data from a given index --- indexer/includes/reparse.php | 8 ++++---- indexer/indexer.php | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/indexer/includes/reparse.php b/indexer/includes/reparse.php index 6c60102..971afde 100644 --- a/indexer/includes/reparse.php +++ b/indexer/includes/reparse.php @@ -2,17 +2,17 @@ /********************************************************************* * reparse.php - Handles reparsing the ledger to re-validate all txs ********************************************************************/ -function btnsReparse($block_index=null){ +function btnsReparse($block_index=null, $start_index=null){ global $mysqli, $runtime; // Placeholder for any error message $error = false; // Notify user of start of reparse - print "Reparsing all transactions...\n"; + print "Reparsing transactions...\n"; - // Start parsing transactions starting at the first block - $block = FIRST_BLOCK; + // Start reparsing transactions at the first block or the given start_index + $block = (isset($start_index) && is_numeric($start_index)) ? $start_index : FIRST_BLOCK; $current = $block_index; // Loop through the blocks until we are current diff --git a/indexer/indexer.php b/indexer/indexer.php index cd0ab92..83c1cf9 100755 --- a/indexer/indexer.php +++ b/indexer/indexer.php @@ -24,7 +24,8 @@ * --testnet Load data from testnet * --block=# Load data for given block * --rollback=# Rollback data to a given block - * --reparse Reparse and validate all transactions + * --reparse Reparse ALL data + * --reparse=# Reparse data from a given block * --single Load single block ********************************************************************/ @@ -35,7 +36,7 @@ $args = getopt("", array("testnet::", "block::", "single::", "rollback::", "reparse::")); $testnet = (isset($args['testnet'])) ? true : false; $single = (isset($args['single'])) ? true : false; -$reparse = (isset($args['reparse'])) ? true : false; +$reparse = (isset($args['reparse'])) ? ((is_numeric($args['reparse'])) ? $args['reparse'] : true) : false; $block = (is_numeric($args['block'])) ? intval($args['block']) : false; $network = ($testnet) ? 'testnet' : 'mainnet'; $rollback = (is_numeric($args['rollback'])) ? intval($args['rollback']) : false; @@ -89,7 +90,7 @@ // Handle reparses if($reparse) - btnsReparse($current); + btnsReparse($current, $reparse); // Loop through the blocks until we are current while($block <= $current){ From f4fe963cbd4edc0d29be3b163923cbf37ea86b82 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Tue, 5 Mar 2024 18:08:04 -0800 Subject: [PATCH 09/42] hashing optimizations updated `getBlockDataHashes()` to generate hashes based off block data + previous hash --- indexer/includes/functions.php | 60 +++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 8154e93..618508e 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1811,57 +1811,85 @@ function getBlockDataHashes($block=null){ return $info; } -// Get block hashes using credits/debits/transactions table data + +// Get block hashes using credits/debits/transactions table data and previous hash function getBlockHashes($block=null){ global $mysqli; $credits = array(); $debits = array(); $txlist = array(); $info = array(); - // Get all block data from credits table - $results = $mysqli->query("SELECT * FROM credits WHERE block_index<='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); + $hashes = array(); + // Get data from credits table + $results = $mysqli->query("SELECT * FROM credits WHERE block_index='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); if($results){ if($results->num_rows){ while($row = $results->fetch_assoc()) - array_push($credits, (object) $row); + array_push($credits, $row); } } else { byeLog('Error while trying to lookup records in credits table'); } - // Get all block data from debits table - $results = $mysqli->query("SELECT * FROM debits WHERE block_index<='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); + // Get data from debits table + $results = $mysqli->query("SELECT * FROM debits WHERE block_index='{$block}' ORDER BY block_index ASC, tick_id ASC, address_id ASC, amount DESC"); if($results){ if($results->num_rows){ while($row = $results->fetch_assoc()) - array_push($debits, (object) $row); + array_push($debits, $row); } } else { byeLog('Error while trying to lookup records in debits table'); } // Get all block data from transactions table - $results = $mysqli->query("SELECT * FROM transactions WHERE block_index<='{$block}' ORDER BY tx_index ASC"); + $results = $mysqli->query("SELECT * FROM transactions WHERE block_index='{$block}' ORDER BY tx_index ASC"); if($results){ if($results->num_rows){ while($row = $results->fetch_assoc()) - array_push($txlist, (object) $row); + array_push($txlist, $row); } } else { byeLog('Error while trying to lookup records in transactions table'); } - // Generate SHA256 hashes based on the json object + // Subtract one block from current block + $block--; + // Get hashes from the last block to include in this blocks hash + $sql = "SELECT + t1.hash as credits, + t2.hash as debits, + t3.hash as txlist + FROM + blocks b, + index_transactions t1, + index_transactions t2, + index_transactions t3 + WHERE + t1.id=b.credits_hash_id AND + t2.id=b.debits_hash_id AND + t3.id=b.txlist_hash_id AND + b.block_index='{$block}'"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows) + $hashes = $results->fetch_assoc(); + } else { + byeLog('Error while trying to lookup records in transactions table'); + } $tables = ['credits','debits','txlist']; - // Loop through the data tables and dump a quick list of tx_index and status + // Loop through the tables, add previous hash to data, then create new block hash foreach($tables as $table){ $data = ${$table}; - $hash = getDataHash($data); - // print "table={$table}\n"; - // print "hash={$hash}\n"; - // print "data=" . count($data) . "\n"; - $info[$table] = ['hash' => $hash]; + // Include the block_index and previous block hash in the hash calculation for this block hash + $data['block_index'] = $block; + $data['previous_hash'] = $hashes[$table]; + $info[$table] = [ + 'hash' => getDataHash($data), + // 'data' => $data, + ]; } return $info; } + // Generalized function to handle processing a broadcast transaction // @param {tx} object Transaction object // @param {tx->source} string Source address From abad1d62453fca54dbb333c4294ff7446c023e28 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 6 Mar 2024 00:02:01 -0800 Subject: [PATCH 10/42] reparse updates / optimizations / cleanup --- indexer/includes/actions/destroy.php | 21 +-- indexer/includes/actions/issue.php | 27 ++-- indexer/includes/actions/list.php | 2 +- indexer/includes/actions/mint.php | 29 ++-- indexer/includes/actions/send.php | 21 +-- indexer/includes/functions.php | 232 +++++++++++++++++---------- indexer/includes/reparse.php | 5 +- indexer/indexer.php | 9 +- 8 files changed, 204 insertions(+), 142 deletions(-) diff --git a/indexer/includes/actions/destroy.php b/indexer/includes/actions/destroy.php index f819b3f..ec7802c 100644 --- a/indexer/includes/actions/destroy.php +++ b/indexer/includes/actions/destroy.php @@ -15,7 +15,7 @@ * ********************************************************************/ function btnsDestroy($params=null, $data=null, $error=null){ - global $mysqli, $reparse, $tickers, $addresses; + global $mysqli, $reparse, $addresses, $tickers; // Define list of known FORMATS $formats = array( @@ -69,18 +69,15 @@ function btnsDestroy($params=null, $data=null, $error=null){ foreach($destroys as $destroy){ $tick = $destroy[0]; if(!$ticks[$tick]) - $ticks[$tick] = getTokenInfo($tick); + $ticks[$tick] = getTokenInfo($tick, null, $data->BLOCK_INDEX, $data->TX_INDEX); } - // Get source address balances - $balances = getAddressBalances($data->SOURCE); + // Get source address balances at the time of the tx + $balances = getAddressBalances($data->SOURCE, null, $data->BLOCK_INDEX, $data->TX_INDEX); // Store original error value $origError = $error; - // Add SOURCE address to the addresses array - $addresses[$data->SOURCE] = 1; - // Array of debits $debits = []; @@ -148,8 +145,8 @@ function btnsDestroy($params=null, $data=null, $error=null){ // If this was a valid transaction, then create debit record if($status=='valid'){ - // Add ticker to tickers array - $tickers[$destroy->TICK] = 1; + // Store the SOURCE and TICK in addresses list + addAddressTicker($destroy->SOURCE, $destroy->TICK); // Add ticker and amount to debits array array_push($debits, array($destroy->TICK, $destroy->AMOUNT)); @@ -165,11 +162,15 @@ function btnsDestroy($params=null, $data=null, $error=null){ createDebit('DESTROY', $data->BLOCK_INDEX, $data->TX_HASH, $tick, $amount, $data->SOURCE); } + // If this is a reparse, bail out before updating balances + if($reparse) + return; + // Update address balances updateBalances(array_keys($addresses)); // Update supply for tokens - updateTokens(array_keys($ticks)); + updateTokens($tickers); } ?> \ No newline at end of file diff --git a/indexer/includes/actions/issue.php b/indexer/includes/actions/issue.php index 250ef1c..259ba75 100644 --- a/indexer/includes/actions/issue.php +++ b/indexer/includes/actions/issue.php @@ -36,7 +36,7 @@ * ********************************************************************/ function btnsIssue( $params=null, $data=null, $error=null){ - global $mysqli, $reparse, $tickers, $addresses; + global $mysqli, $reparse, $addresses, $tickers; // Define list of known FORMATS $formats = array( @@ -98,15 +98,18 @@ function btnsIssue( $params=null, $data=null, $error=null){ $error = 'invalid: GAS_ADDRESS'; // Get information on BTNS token - $btInfo = getTokenInfo($data->TICK); + $btInfo = getTokenInfo($data->TICK, null, $data->BLOCK_INDEX, $data->TX_INDEX); $isDistributed = isDistributed($data->TICK); + // Clone the raw data for storage in issues table + $issue = clone($data); + // Populate empty PARAMS with current setting if($btInfo){ foreach($btInfo as $key => $value) if(!$data->{$key}) $data->{$key} = $value; - } + } // If BTNS Token does not exist yet, do some additional validations if(!$btInfo){ @@ -164,11 +167,11 @@ function btnsIssue( $params=null, $data=null, $error=null){ } // Verify MAX_SUPPLY min/max - if(!$error && isset($data->MAX_SUPPLY) && ($data->MAX_SUPPLY < MIN_TOKEN_SUPPLY || $data->MAX_SUPPLY > MAX_TOKEN_SUPPLY)) + if(!$error && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY > 0 && ($data->MAX_SUPPLY < MIN_TOKEN_SUPPLY || $data->MAX_SUPPLY > MAX_TOKEN_SUPPLY)) $error = 'invalid: MAX_SUPPLY (min/max)'; // Verify MAX_SUPPLY is not set below current SUPPLY - if(!$error && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY < $data->SUPPLY) + if(!$error && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY > 0 && $data->MAX_SUPPLY < getTokenSupply($data->TICK, $data->BLOCK_INDEX, $data->TX_INDEX)) $error = 'invalid: MAX_SUPPLY < SUPPLY'; // Verify SUPPLY is at least MIN_TOKEN_SUPPLY before allowing LOCK_SUPPLY @@ -272,27 +275,17 @@ function btnsIssue( $params=null, $data=null, $error=null){ $error = 'invalid: MINT_STOP_BLOCK < MINT_START_BLOCK'; // Determine final status - $data->STATUS = $status = ($error) ? $error : 'valid'; + $data->STATUS = $issue->STATUS = $status = ($error) ? $error : 'valid'; // Print status message print "\n\t ISSUE : {$data->TICK} : {$data->STATUS}"; // Create record in issues table - createIssue($data); + createIssue($issue); // If this was a valid transaction, then create the token record, and perform any additional actions if($status=='valid'){ - // Add the ticker to the tickers array - $tickers[$data->TICK] = 1; - - // Add any addresses to the addresses array - $addresses[$data->SOURCE] = 1; - if($data->TRANSFER) - $addresses[$data->TRANSFER] = 1; - if($data->TRANSFER_SUPPLY) - $addresses[$data->TRANSFER_SUPPLY] = 1; - // Support token ownership transfers $data->OWNER = (isset($data->TRANSFER)) ? $data->TRANSFER : $data->SOURCE; diff --git a/indexer/includes/actions/list.php b/indexer/includes/actions/list.php index d7f48ee..fd1d172 100644 --- a/indexer/includes/actions/list.php +++ b/indexer/includes/actions/list.php @@ -15,7 +15,7 @@ * ********************************************************************/ function btnsList( $params=null, $data=null, $error=null){ - global $mysqli, $reparse, $tickers, $addresses; + global $mysqli, $reparse, $addresses, $tickers; // Define list of known FORMATS $formats = array( diff --git a/indexer/includes/actions/mint.php b/indexer/includes/actions/mint.php index 3a70a22..041f1d5 100644 --- a/indexer/includes/actions/mint.php +++ b/indexer/includes/actions/mint.php @@ -13,7 +13,7 @@ * ********************************************************************/ function btnsMint($params=null, $data=null, $error=null){ - global $mysqli, $reparse, $tickers, $addresses; + global $mysqli, $reparse, $addresses, $tickers; // Define list of known FORMATS $formats = array( @@ -36,7 +36,14 @@ function btnsMint($params=null, $data=null, $error=null){ $data = setActionParams($data, $params, $formats[$format]); // Get information on BTNS token - $btInfo = getTokenInfo($data->TICK); + $btInfo = getTokenInfo($data->TICK, null, $data->BLOCK_INDEX, $data->TX_INDEX); + + // Clone the raw data for storage in mints table + $mint = clone($data); + + // Verify TICK is valid before MINT + if($btInfo->BLOCK_INDEX==$data->BLOCK_INDEX && !validTickerBeforeTxIndex($data->TICK, $data->TX_INDEX)) + unset($btInfo); // Set divisible flag $divisible = ($btInfo->DECIMALS==0) ? 0 : 1; @@ -93,7 +100,7 @@ function btnsMint($params=null, $data=null, $error=null){ $error = 'invalid: DESTINATION (not authorized)'; // Verify minting AMOUNT will not exceed MINT_ADDRESS_MAX - if(!$error && isset($data->MINT_ADDRESS_MAX) && $data->MINT_ADDRESS_MAX > 0 && (bcadd(getActionCreditDebitAmount('credits', 'MINT', $data->TICK, $data->SOURCE),$data->AMOUNT,$data->DECIMALS) > $data->MINT_ADDRESS_MAX)) + if(!$error && isset($data->MINT_ADDRESS_MAX) && $data->MINT_ADDRESS_MAX > 0 && (bcadd(getActionCreditDebitAmount('credits', 'MINT', $data->TICK, $data->SOURCE, $data->TX_INDEX),$data->AMOUNT,$data->DECIMALS) > $data->MINT_ADDRESS_MAX)) $error = 'invalid: mint exceeds MINT_ADDRESS_MAX'; // Verify minting begins at MINT_START_BLOCK @@ -105,27 +112,17 @@ function btnsMint($params=null, $data=null, $error=null){ $error = 'invalid: MINT_STOP_BLOCK'; // Determine final status - $data->STATUS = $status = ($error) ? $error : 'valid'; + $data->STATUS = $mint->STATUS = $status = ($error) ? $error : 'valid'; // Print status message print "\n\t MINT : {$data->TICK} : {$data->AMOUNT} : {$data->STATUS}"; // Create record in mints table - createMint($data); + createMint($mint); // If this was a valid transaction, then mint any actual supply if($status=='valid'){ - // Add the ticker to the tickers array - $tickers[$data->TICK] = 1; - - // Add SOURCE address to the addresses array - $addresses[$data->SOURCE] = 1; - - // Add DESTINATION address to the addresses array - if($data->DESTINATION) - $addresses[$data->DESTINATION] = 1; - // Credit MINT_SUPPLY to source address if($data->AMOUNT){ createCredit('MINT', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->AMOUNT, $data->SOURCE); @@ -140,7 +137,7 @@ function btnsMint($params=null, $data=null, $error=null){ // If this is a reparse, bail out before updating balances and token information if($reparse) return; - + // Update balances for addresses updateBalances([$data->SOURCE, $data->DESTINATION]); diff --git a/indexer/includes/actions/send.php b/indexer/includes/actions/send.php index ae78ee5..8081706 100644 --- a/indexer/includes/actions/send.php +++ b/indexer/includes/actions/send.php @@ -17,7 +17,7 @@ * ********************************************************************/ function btnsSend($params=null, $data=null, $error=null){ - global $mysqli, $reparse, $tickers, $addresses; + global $mysqli, $reparse, $addresses, $tickers; // Define list of known FORMATS $formats = array( @@ -87,16 +87,12 @@ function btnsSend($params=null, $data=null, $error=null){ $ticks[$tick] = getTokenInfo($tick); } - // Get source address balances - // TODO : add block index to get balances as of block X - $balances = getAddressBalances($data->SOURCE); + // Get source address balances + $balances = getAddressBalances($data->SOURCE, null, $data->BLOCK_INDEX, $data->TX_INDEX); // Store original error value $origError = $error; - // Add SOURCE address to the addresses array - $addresses[$data->SOURCE] = 1; - // Array of credits and debits $credits = []; $debits = []; @@ -178,11 +174,8 @@ function btnsSend($params=null, $data=null, $error=null){ // If this was a valid transaction, then add records to the credits and debits array if($status=='valid'){ - // Add ticker to tickers array - $tickers[$send->TICK] = 1; - - // Add destination address to addresses array - $addresses[$send->DESTINATION] = 1; + // Store the DESTINATION and TICK in addresses list + addAddressTicker($send->DESTINATION, $send->TICK); // Add ticker and amount to debits array array_push($debits, array($send->TICK, $send->AMOUNT)); @@ -212,8 +205,10 @@ function btnsSend($params=null, $data=null, $error=null){ if($reparse) return; + // Store the SOURCE and TICKERS in addresses list + addAddressTicker($send->SOURCE, $tickers); + // Update address balances - // TODO: Optimize this to only update balances for ticks, not full balances... its way too slow now updateBalances(array_keys($addresses)); } diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 618508e..e4b7fcd 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -26,7 +26,6 @@ function createLockFile($file=null){ } } - // Handle removing a lockfile function removeLockFile($file=null){ $lockFile = ($file!='') ? $file : LOCKFILE; @@ -145,7 +144,6 @@ function createTicker( $tick=null ){ } } - // Create records in the 'index_statuses' table and return record id function createStatus( $status=null ){ global $mysqli; @@ -314,7 +312,6 @@ function createIssue( $data=null ){ } } - // Create record in `mints` table function createMint( $data=null ){ global $mysqli; @@ -547,9 +544,6 @@ function createToken( $data=null ){ } } - - - // Create record in `credits` table function createCredit( $action=null, $block_index=null, $event=null, $tick=null, $amount=null, $address=null ){ global $mysqli; @@ -659,10 +653,13 @@ function createBlock( $block=null ){ byeLog('Error while trying to lookup records in credits table'); } // Get a list of hashes for this block - $info = getBlockHashes($block); - $credits_hash_id = createTransaction($info['credits']['hash']); - $debits_hash_id = createTransaction($info['debits']['hash']); - $txlist_hash_id = createTransaction($info['txlist']['hash']); + $info = getBlockHashes($block); + $credits = $info['credits']['hash']; + $debits = $info['debits']['hash']; + $txlist = $info['txlist']['hash']; + $credits_hash_id = createTransaction($credits); + $debits_hash_id = createTransaction($debits); + $txlist_hash_id = createTransaction($txlist); // Check if record already exists $results = $mysqli->query("SELECT id FROM blocks WHERE block_index='{$block}'"); if($results){ @@ -805,7 +802,6 @@ function createListEdit($data=null, $item=null, $status=null ){ } } - // Create record in `list_items` table function createListItem($data=null, $item=null){ global $mysqli; @@ -831,7 +827,6 @@ function createListItem($data=null, $item=null){ } } - // Delete records in lists, list_items, and list_edits tables function deleteLists($list=null, $rollback=null){ global $mysqli; @@ -862,14 +857,19 @@ function deleteLists($list=null, $rollback=null){ } } - -// Handle getting token information for a given tick -function getTokenInfo($tick=null, $tick_id=null, $block_index=null){ +// Handle getting token information using issues table +function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=null){ global $mysqli; - $data = false; + $data = false; + $whereSql = ""; if(!is_null($tick) && is_null($tick_id)) $tick_id = createTicker($tick); - // Get data from tokens table + // If a block index was given, only lookup tokens created before or in given block + if(isset($block_index) && is_numeric($block_index)) + $whereSql .= " AND t1.block_index <= {$block_index}"; + if(isset($tx_index) && is_numeric($tx_index)) + $whereSql .= " AND t1.tx_index < '{$tx_index}'"; + // Get data from issues table $sql = "SELECT t2.tick, t1.max_supply, @@ -877,7 +877,6 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null){ t1.decimals, t1.description, t1.block_index, - t1.supply, t1.lock_supply, t1.lock_mint, t1.lock_description, @@ -892,54 +891,72 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null){ t1.mint_address_max, t1.mint_start_block, t1.mint_stop_block, - a.address as owner + a1.address as owner, + a2.address as transfer FROM - tokens t1 + issues t1 + LEFT JOIN index_addresses a2 on (a2.id=t1.transfer_id) LEFT JOIN index_tickers t3 on (t3.id=t1.callback_tick_id) LEFT JOIN index_transactions t4 on (t4.id=t1.allow_list_id) LEFT JOIN index_transactions t5 on (t5.id=t1.block_list_id), index_tickers t2, - index_addresses a + index_addresses a1 WHERE t2.id=t1.tick_id AND - a.id=t1.owner_id AND - t1.tick_id='{$tick_id}'"; - // If a block index was given, only lookup token information before given block - if(isset($block_index) && is_numeric($block_index)) - $sql .= " AND t1.block_index <= {$block_index}"; + a1.id=t1.source_id AND + t1.status_id=1 AND + t1.tick_id='{$tick_id}' + {$whereSql} + ORDER BY tx_index ASC"; // print $sql; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ - $row = (object) $results->fetch_assoc(); - $data = (object) array( - 'TICK' => $row->tick, - 'BLOCK_INDEX' => $row->block_index, - 'MAX_SUPPLY' => $row->max_supply, - 'MAX_MINT' => $row->max_mint, - 'DECIMALS' => $row->decimals, - 'DESCRIPTION' => $row->description, - 'SUPPLY' => $row->supply, - 'OWNER' => $row->owner, - 'LOCK_SUPPLY' => $row->lock_supply, - 'LOCK_MINT' => $row->lock_mint, - 'LOCK_DESCRIPTION' => $row->lock_description, - 'LOCK_RUG' => $row->lock_rug, - 'LOCK_SLEEP' => $row->lock_sleep, - 'LOCK_CALLBACK' => $row->lock_callback, - 'CALLBACK_TICK' => $row->callback_tick, - 'CALLBACK_BLOCK' => $row->callback_block, - 'CALLBACK_AMOUNT' => $row->callback_amount, - 'ALLOW_LIST' => $row->allow_list, - 'BLOCK_LIST' => $row->block_list, - 'MINT_ADDRESS_MAX' => $row->mint_address_max, - 'MINT_START_BLOCK' => $row->mint_start_block, - 'MINT_STOP_BLOCK' => $row->mint_stop_block - ); + // Loop through issues before tx_index + while($row = $results->fetch_assoc()){ + $row = (object) $row; + $arr = array( + 'TICK' => $row->tick, + 'OWNER' => ($row->transfer) ? $row->transfer : $row->owner, + 'MAX_SUPPLY' => $row->max_supply, + 'MAX_MINT' => $row->max_mint, + 'DECIMALS' => $row->decimals, + 'DESCRIPTION' => $row->description, + 'OWNER' => $row->owner, + 'LOCK_SUPPLY' => $row->lock_supply, + 'LOCK_MINT' => $row->lock_mint, + 'LOCK_DESCRIPTION' => $row->lock_description, + 'LOCK_RUG' => $row->lock_rug, + 'LOCK_SLEEP' => $row->lock_sleep, + 'LOCK_CALLBACK' => $row->lock_callback, + 'CALLBACK_TICK' => $row->callback_tick, + 'CALLBACK_BLOCK' => $row->callback_block, + 'CALLBACK_AMOUNT' => $row->callback_amount, + 'ALLOW_LIST' => $row->allow_list, + 'BLOCK_LIST' => $row->block_list, + 'MINT_ADDRESS_MAX' => $row->mint_address_max, + 'MINT_START_BLOCK' => $row->mint_start_block, + 'MINT_STOP_BLOCK' => $row->mint_stop_block + ); + // build out token state before tx_index + // TODO: will need to massage the data a bit more to build out accurate token state... this is quick and dirty + foreach($arr as $key => $value){ + // Disallow unsetting of LOCK flags + if(substr($key,0,5)=='LOCK_') + if($data[$key]==1) + continue; + $data[$key] = $value; + } + } } } else { byeLog("Error while trying to lookup token info for : {$tick}"); } + if($data){ + // Get token supply at the given tx_index + $data['SUPPLY'] = getTokenSupply($tick, null, $tx_index); + $data = (object) $data; + } return $data; } @@ -1034,7 +1051,7 @@ function getTokenDecimalPrecision($tick_id=null){ } // Handle getting credits or debits records for a given address -function getAddressCreditDebit($table=null, $address=null, $action=null, $block=null){ +function getAddressCreditDebit($table=null, $address=null, $action=null, $block=null, $tx_index=null){ global $mysqli; $data = array(); // Assoc array to store tick/credits $type = gettype($address); @@ -1044,6 +1061,14 @@ function getAddressCreditDebit($table=null, $address=null, $action=null, $block= $address_id = createAddress($address); if(isset($action)) $action_id = createAction($action); + // Build out custom WHERE sql + $whereSql = ""; + if(isset($action)) + $whereSql .= " AND t1.action_id={$action_id}"; + if(isset($block) && is_numeric($block)) + $whereSql .= " AND t1.block_index < {$block}"; + if(isset($tx_index) && is_numeric($tx_index)) + $whereSql .= " AND t3.tx_index < {$tx_index}"; if(in_array($table,array('credits','debits'))){ // Get data from the table $sql = "SELECT @@ -1052,14 +1077,13 @@ function getAddressCreditDebit($table=null, $address=null, $action=null, $block= t2.decimals FROM {$table} t1, - tokens t2 + tokens t2, + transactions t3 WHERE t2.tick_id=t1.tick_id AND - t1.address_id='{$address_id}'"; - if(isset($action)) - $sql .= " AND t1.action_id={$action_id}"; - if(isset($block) && is_numeric($block)) - $sql .= " AND t1.block_index < {$block}"; + t3.tx_hash_id=t1.event_id AND + t1.address_id='{$address_id}' + {$whereSql}"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ @@ -1079,15 +1103,15 @@ function getAddressCreditDebit($table=null, $address=null, $action=null, $block= } // Get address balances using credits/debits table data -function getAddressBalances($address=null, $tick=null, $block=null){ +function getAddressBalances($address=null, $tick=null, $block=null, $tx_index=null){ global $mysqli; $type = gettype($address); if($type==='integer' || is_numeric($address)) $address_id = $address; if($type==='string' && !is_numeric($address)) $address_id = createAddress($address); - $credits = getAddressCreditDebit('credits', $address_id, null, $block); - $debits = getAddressCreditDebit('debits', $address_id, null, $block); + $credits = getAddressCreditDebit('credits', $address_id, null, $block, $tx_index); + $debits = getAddressCreditDebit('debits', $address_id, null, $block, $tx_index); $decimals = array(); // Assoc array to store tick/decimals $balances = array(); // Assoc array to store tick/balance foreach($credits as $tick_id => $amount) @@ -1133,11 +1157,10 @@ function getAddressTableBalances($address=null){ return $balances; } - // Create/Update/Delete records in the 'balances' table function updateAddressBalance( $address=null, $rollback=false){ global $mysqli; - // print "updateAddressBalance address={$address}\n"; + // print "updateAddressBalance address={$address} rollback={$rollback}\n"; $type = gettype($address); if($type==='integer' || is_numeric($address)) $address_id = $address; @@ -1187,8 +1210,6 @@ function updateAddressBalance( $address=null, $rollback=false){ } } - - // Handle updating address balances (credits-debits=balance) // @param {address} boolean Full update // @param {address} string Address string @@ -1198,10 +1219,11 @@ function updateBalances( $address=null, $rollback=false ){ global $mysqli; $addrs = []; $type = gettype($address); - if($type==='array') + if($type==='array'){ foreach($address as $addr) if(!is_null($addr) && $addr!='') array_push($addrs, $addr); + } if($type==='string') array_push($addrs, $address); // Dump full list of addresses @@ -1220,7 +1242,6 @@ function updateBalances( $address=null, $rollback=false ){ updateAddressBalance($address, $rollback); } - // Handle updating token information (supply, price, etc) // @param {tickers} boolean Full update // @param {tickers} string Ticker @@ -1267,7 +1288,10 @@ function updateTokenInfo( $tick=null ){ } // Get token supply from credits/debits table (credits - debits = supply) -function getTokenSupply( $tick=null, $block_index=null ){ +// @param {tick} string Ticker name +// @param {block_index} integer Block Index +// @param {tx_index} integer tx_index of transaction +function getTokenSupply( $tick=null, $block_index=null, $tx_index=null ){ global $mysqli; $credits = 0; $debits = 0; @@ -1276,8 +1300,23 @@ function getTokenSupply( $tick=null, $block_index=null ){ $tick_id = createTicker($tick); // Get info on decimal precision $decimals = getTokenDecimalPrecision($tick_id); + $whereSql = ""; + // Filter by block_index + if(is_numeric($block)) + $whereSql .= " AND m.block_index <= '{$block}'"; + // Filter by tx_index + if(is_numeric($tx_index)) + $whereSql .= " AND t.tx_index < {$tx_index}"; // Get Credits - $sql = "SELECT CAST(SUM(amount) AS DECIMAL(60,$decimals)) as credits FROM credits WHERE tick_id='{$tick_id}' AND block_index<='{$block}'"; + $sql = "SELECT + CAST(SUM(m.amount) AS DECIMAL(60,$decimals)) as credits + FROM + credits m, + transactions t + WHERE + m.event_id=t.tx_hash_id AND + m.tick_id='{$tick_id}' + {$whereSql}"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ @@ -1288,7 +1327,15 @@ function getTokenSupply( $tick=null, $block_index=null ){ byeLog('Error while trying to get list of credits'); } // Get Debits - $sql = "SELECT CAST(SUM(amount) AS DECIMAL(60,$decimals)) as debits FROM debits WHERE tick_id='{$tick_id}' AND block_index<='{$block}'"; + $sql = "SELECT + CAST(SUM(m.amount) AS DECIMAL(60,$decimals)) as debits + FROM + debits m, + transactions t + WHERE + m.event_id=t.tx_hash_id AND + m.tick_id='{$tick_id}' + {$whereSql}"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ @@ -1323,7 +1370,6 @@ function getTokenSupplyBalance( $tick=null ){ return $supply; } - // Handle doing VERY lose validation on an address function isCryptoAddress( $address=null ){ $len = strlen($address); @@ -1336,7 +1382,6 @@ function isCryptoAddress( $address=null ){ return false; } - // Generalized function to invoke BTNS action commands function btnsAction($action=null, $params=null, $data=null, $error=null){ if($action=='AIRDROP') btnsAirdrop($params, $data, $error); @@ -1355,7 +1400,6 @@ function btnsAction($action=null, $params=null, $data=null, $error=null){ if($action=='SWEEP') btnsSweep($params, $data, $error); } - // Create records in the 'tx_index_types' table and return record id function createTxType( $type=null ){ global $mysqli; @@ -1406,7 +1450,6 @@ function getTxIndex($tx_hash=null){ } } - // Create records in the 'transactions' table function createTxIndex( $data=null ){ global $mysqli; @@ -1746,12 +1789,12 @@ function consolidateCreditDebitRecords($type=null, $records=null){ } // Get total amount of credit or debit records for a given address, ticker, and action -function getActionCreditDebitAmount($table=null, $action=null, $tick=null, $address=null){ +function getActionCreditDebitAmount($table=null, $action=null, $tick=null, $address=null, $tx_index=null){ global $mysqli; $total = 0; $tick_id = createTicker($tick); $addr_id = createAddress($address); - $data = getAddressCreditDebit($table, $addr_id, $action); + $data = getAddressCreditDebit($table, $addr_id, $action, null, $tx_index); if($data[$tick_id]) $total = $data[$tick_id]; return $total; @@ -1811,7 +1854,6 @@ function getBlockDataHashes($block=null){ return $info; } - // Get block hashes using credits/debits/transactions table data and previous hash function getBlockHashes($block=null){ global $mysqli; @@ -1889,7 +1931,6 @@ function getBlockHashes($block=null){ return $info; } - // Generalized function to handle processing a broadcast transaction // @param {tx} object Transaction object // @param {tx->source} string Source address @@ -1898,9 +1939,6 @@ function getBlockHashes($block=null){ // @param {$tx->tx_hash} string Transaction hash // @param {$tx->block_index} string Block index of tx function processTransaction($tx=null){ - // Assoc arrays to track address/ticker changes - $addresses = array(); - $tickers = array(); $error = false; $tx = (object) $tx; $prefixes = array('/^bt:/','/^btns:/'); @@ -2015,4 +2053,36 @@ function validTickerBeforeTxIndex($tick=null, $txIndex=null){ return false; } +// Handle adding a ticker to the $addresses assoc array and $tickers array +function addAddressTicker($address=null, $tick=null){ + global $addresses, $tickers; + $type = gettype($tick); + $list = (isset($addresses[$address])) ? $addresses[$address] : []; + // If $tick is an array, use the array + if($type=="array"){ + $list = $tick; + } else { + // Add TICK to $addresses + if(!in_array($tick, $list)) + array_push($list, $tick); + // Add TICK to $tickers + if(!in_array($tick, $tickers)) + array_push($tickers, $tick); + } + $addresses[$address] = $list; +} + +// Handle displaying runtime information in a nice format +function printRuntime($seconds){ + $msg = ""; + $hours = floor($seconds / 3600); + $mins = floor(($seconds / 60) % 60); + $secs = $seconds % 60; + $ms = explode(".",$seconds)[1]; + if($hours>0) $msg .= "{$hours} hours "; + if($mins>0) $msg .= "{$mins} minutes "; + if($secs>0) $msg .= "{$secs}.{$ms} seconds"; + print "Total Execution time: {$msg}\n"; +} + ?> diff --git a/indexer/includes/reparse.php b/indexer/includes/reparse.php index 971afde..9f8d8e5 100644 --- a/indexer/includes/reparse.php +++ b/indexer/includes/reparse.php @@ -74,12 +74,11 @@ function btnsReparse($block_index=null, $start_index=null){ $block++; } - // Notify user of the total reparse time - print "Total Execution time: " . $runtime->finish() ." seconds\n"; + // Print out information on the total runtime + printRuntime($runtime->finish()); // Notify user reparse is complete byeLog("Reparse complete."); - } ?> diff --git a/indexer/indexer.php b/indexer/indexer.php index 83c1cf9..7217cc8 100755 --- a/indexer/indexer.php +++ b/indexer/indexer.php @@ -62,6 +62,10 @@ // Create a lock file, and bail if we detect an instance is already running createLockFile(); +// Define global assoc arrays to track address/ticker changes +$addresses = []; +$tickers = []; + // Handle rollbacks if($rollback) btnsRollback($rollback); @@ -129,4 +133,7 @@ // Remove the lockfile now that we are done running removeLockFile(); -print "Total Execution time: " . $runtime->finish() ." seconds\n"; +// Print out information on the total runtime +printRuntime($runtime->finish()); + +?> \ No newline at end of file From 8e468c32c49ee07ae456ee70d0bfd18c691c04e4 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 6 Mar 2024 12:57:43 -0800 Subject: [PATCH 11/42] add `ADDRESS` action --- docs/BTNS-420.md | 1 + docs/actions/ADDRESS.md | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 docs/actions/ADDRESS.md diff --git a/docs/BTNS-420.md b/docs/BTNS-420.md index 4942046..3a08d8b 100644 --- a/docs/BTNS-420.md +++ b/docs/BTNS-420.md @@ -62,6 +62,7 @@ Below is a list of the defined BTNS `ACTION` commands and the function of each: | ACTION | Description | | ------------------------------------- | ------------------------------------------------------------------------------------------------- | +| [`ADDRESS`](./actions/ADDRESS.md) | Configures address specific options. | | [`AIRDROP`](./actions/AIRDROP.md) | Transfer/Distribute `token` supply to a `LIST` | | [`BATCH`](./actions/BATCH.md) | Execute multiple BTNS `ACTION` commands in a single transaction | | [`BET`](./actions/BET.md) | Bet `token` on `broadcast` oracle feed outcomes | diff --git a/docs/actions/ADDRESS.md b/docs/actions/ADDRESS.md new file mode 100644 index 0000000..5c34c74 --- /dev/null +++ b/docs/actions/ADDRESS.md @@ -0,0 +1,37 @@ +# ADDRESS command +This command configures address specific options. + +## PARAMS +| Name | Type | Description | +| ---------------- | ------ | ----------------------------------------| +| `VERSION` | String | Broadcast Format Version | +| `FEE_PREFERENCE` | String | Set preference for how `FEE` is used | +| `REQUIRE_MEMO` | String | Require a `MEMO` on any received `SEND` | + +## Formats + +### Version `0` +- `VERSION|FEE_PREFERENCE|REQUIRE_MEMO` + +## Examples +``` +bt:ADDRESS|0|1|0 +This example sets the address to DESTROY fees +``` + +``` +bt:ADDRESS|0|2|0 +This example sets the address to DONATE fees +``` + +``` +bt:ADDRESS|0|0|1 +This example sets the address to require a `MEMO` on any received `SEND` +``` + +## `FEE_PREFERENCE` Options +- `1` = Destroy `FEE`, provably lowering supply +- `2` = Donate `FEE` to protocol development (default) +- `3` = Donate `FEE` to community development + +## Notes From fe1f7f2e4965d94b6c3f0f8c2ade1e154ee59064 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 6 Mar 2024 12:58:54 -0800 Subject: [PATCH 12/42] cleanup --- docs/BTNS-420.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/BTNS-420.md b/docs/BTNS-420.md index 3a08d8b..a20e527 100644 --- a/docs/BTNS-420.md +++ b/docs/BTNS-420.md @@ -62,7 +62,7 @@ Below is a list of the defined BTNS `ACTION` commands and the function of each: | ACTION | Description | | ------------------------------------- | ------------------------------------------------------------------------------------------------- | -| [`ADDRESS`](./actions/ADDRESS.md) | Configures address specific options. | +| [`ADDRESS`](./actions/ADDRESS.md) | Configures address specific options | | [`AIRDROP`](./actions/AIRDROP.md) | Transfer/Distribute `token` supply to a `LIST` | | [`BATCH`](./actions/BATCH.md) | Execute multiple BTNS `ACTION` commands in a single transaction | | [`BET`](./actions/BET.md) | Bet `token` on `broadcast` oracle feed outcomes | From 8a3e7eca3a8f4f6b13e3fe534afa24d946cd5660 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 6 Mar 2024 13:06:50 -0800 Subject: [PATCH 13/42] add `ADDRESS` / remove `BET` - add `ADDRESS` action to readme - removed `BET` action from BTNS-420 and readme Note: BET action can be built out in XChain platform --- README.md | 2 +- docs/BTNS-420.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 7442c97..be6bbbe 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,9 @@ Name | Title | Aut | ACTION | Description | | ------------------------------------------ | ------------------------------------------------------------------------------------------------- | +| [`ADDRESS`](./docs/actions/ADDRESS.md) | Configure address specific options | | [`AIRDROP`](./docs/actions/AIRDROP.md) | Transfer/Distribute `token` supply to a `LIST` | | [`BATCH`](./docs/actions/BATCH.md) | Execute multiple BTNS `ACTION` commands in a single transaction | -| [`BET`](./docs/actions/BET.md) | Bet `token` on `broadcast` oracle feed outcomes | | [`CALLBACK`](./docs/actions/CALLBACK.md) | Return all `token` supply to owner address after a set block, in exchange for a different `token` | | [`DESTROY`](./docs/actions/DESTROY.md) | Destroy `token` supply forever | | [`DISPENSER`](./docs/actions/DISPENSER.md) | Create a dispenser (vending machine) to dispense a `token` when triggered | diff --git a/docs/BTNS-420.md b/docs/BTNS-420.md index a20e527..a7b2a0e 100644 --- a/docs/BTNS-420.md +++ b/docs/BTNS-420.md @@ -65,7 +65,6 @@ Below is a list of the defined BTNS `ACTION` commands and the function of each: | [`ADDRESS`](./actions/ADDRESS.md) | Configures address specific options | | [`AIRDROP`](./actions/AIRDROP.md) | Transfer/Distribute `token` supply to a `LIST` | | [`BATCH`](./actions/BATCH.md) | Execute multiple BTNS `ACTION` commands in a single transaction | -| [`BET`](./actions/BET.md) | Bet `token` on `broadcast` oracle feed outcomes | | [`CALLBACK`](./actions/CALLBACK.md) | Return all `token` supply to owner address after a set block, in exchange for a different `token` | | [`DESTROY`](./actions/DESTROY.md) | Destroy `token` supply forever | | [`DISPENSER`](./actions/DISPENSER.md) | Create a dispenser (vending machine) to dispense a `token` when triggered | From 20a415bd244162992b0aadc0bc456381c39ce0d9 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 10:01:31 -0800 Subject: [PATCH 14/42] =?UTF-8?q?cleanup=20checking=20for=20=E2=80=98valid?= =?UTF-8?q?=E2=80=99=20tx=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- indexer/includes/functions.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index e4b7fcd..e8ee4fc 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -900,19 +900,20 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu LEFT JOIN index_transactions t4 on (t4.id=t1.allow_list_id) LEFT JOIN index_transactions t5 on (t5.id=t1.block_list_id), index_tickers t2, - index_addresses a1 + index_addresses a1, + index_statuses s1 WHERE t2.id=t1.tick_id AND a1.id=t1.source_id AND - t1.status_id=1 AND + s1.id=t1.status_id AND + s1.status='valid' AND t1.tick_id='{$tick_id}' {$whereSql} ORDER BY tx_index ASC"; - // print $sql; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ - // Loop through issues before tx_index + // Loop through issues while($row = $results->fetch_assoc()){ $row = (object) $row; $arr = array( @@ -2032,7 +2033,16 @@ function getBroadcastTransactions($block){ function getFirstIssuanceTxIndex($tick=null){ global $mysqli; $tick_id = createTicker($tick); - $sql = "SELECT tx_index FROM issues WHERE tick_id={$tick_id} AND status_id=1 ORDER BY tx_index ASC LIMIT 1"; + $sql = "SELECT + tx_index + FROM + issues i, + index_statuses s + WHERE + i.tick_id={$tick_id} AND + s.id=i.status_id AND + s.status='valid' + ORDER BY tx_index ASC LIMIT 1"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ From 3520fdedc8c453d49e898773124a61c4f10bbae7 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 10:02:59 -0800 Subject: [PATCH 15/42] remove duplicated `getTokenSupply()` call --- indexer/includes/functions.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index e8ee4fc..30e8b41 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1280,12 +1280,9 @@ function updateTokenInfo( $tick=null ){ $tick_id = createTicker($tick); // Lookup current token information $data = getTokenInfo($tick); - if($data){ - // Get current token supply (current token supply) - $data->SUPPLY = getTokenSupply($tick); - // Update the record in `tokens` table + // Update the record in `tokens` table + if($data) createToken($data); - } } // Get token supply from credits/debits table (credits - debits = supply) From 904561f803686d687520e58991b1ce2ea95b2712 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 11:14:37 -0800 Subject: [PATCH 16/42] add `ADDRESS` support --- docs/actions/ADDRESS.md | 2 + indexer/includes/actions/address.php | 96 +++++++++++++++++++++++++++ indexer/includes/config.php | 11 ++- indexer/includes/functions.php | 57 ++++++++++++++-- indexer/includes/protocol_changes.php | 1 + indexer/sql/addresses.sql | 16 +++++ 6 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 indexer/includes/actions/address.php create mode 100644 indexer/sql/addresses.sql diff --git a/docs/actions/ADDRESS.md b/docs/actions/ADDRESS.md index 5c34c74..4e9fdff 100644 --- a/docs/actions/ADDRESS.md +++ b/docs/actions/ADDRESS.md @@ -35,3 +35,5 @@ This example sets the address to require a `MEMO` on any received `SEND` - `3` = Donate `FEE` to community development ## Notes +- `ADDR` `ACTION` can be used for shorter reference to `ADDRESS` `ACTION` + diff --git a/indexer/includes/actions/address.php b/indexer/includes/actions/address.php new file mode 100644 index 0000000..f3c6ffd --- /dev/null +++ b/indexer/includes/actions/address.php @@ -0,0 +1,96 @@ + 'VERSION|FEE_PREFERENCE|REQUIRE_MEMO' + ); + + /***************************************************************** + * DEBUGGING - Force params + ****************************************************************/ + // $str = "0|1|1"; + // $params = explode('|',$str); + + // Validate that broadcast format is known + $format = getFormatVersion($params[0]); + if(!$error && ($format===NULL || !in_array($format,array_keys($formats)))) + $error = 'invalid: VERSION (unknown)'; + + // Parse PARAMS using given VERSION format and update BTNS transaction data object + if(!$error) + $data = setActionParams($data, $params, $formats[$format]); + + /***************************************************************** + * FORMAT Validations + ****************************************************************/ + + // Verify FEE_PREFERENCE is numeric + if(!$error && isset($data->FEE_PREFERENCE) && !is_numeric($data->FEE_PREFERENCE)) + $error = "invalid: FEE_PREFERENCE (format)"; + + // Verify REQUIRE_MEMO is numeric + if(!$error && isset($data->REQUIRE_MEMO) && !is_numeric($data->REQUIRE_MEMO)) + $error = "invalid: REQUIRE_MEMO (format)"; + + /***************************************************************** + * General Validations + ****************************************************************/ + + // Verify FEE_PREFERENCE value is valid + if(!$error && isset($data->FEE_PREFERENCE) && !in_array($data->FEE_PREFERENCE,array(0,1,2))) + $error = 'invalid: FEE_PREFERENCE'; + + // Verify REQUIRE_MEMO value is valid + if(!$error && isset($data->REQUIRE_MEMO) && !in_array($data->REQUIRE_MEMO,array(0,1))) + $error = 'invalid: REQUIRE_MEMO'; + + // Determine final status + $data->STATUS = $status = ($error) ? $error : 'valid'; + + // Print status message + print "\n\t ADDRESS : {$data->SOURCE} : {$data->STATUS}"; + + // Create record in addresses table + createAddressOption($data); + + // If this was a valid transaction, then mint any actual supply + if($status=='valid'){ + + // Credit MINT_SUPPLY to source address + if($data->AMOUNT){ + createCredit('MINT', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->AMOUNT, $data->SOURCE); + + // Transfer AMOUNT to DESTINATION address + if($data->DESTINATION){ + createDebit('MINT', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->AMOUNT, $data->SOURCE); + createCredit('MINT', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->AMOUNT, $data->DESTINATION); + } + } + + // If this is a reparse, bail out before updating balances and token information + if($reparse) + return; + + // Update balances for addresses + updateBalances([$data->SOURCE, $data->DESTINATION]); + + // Update supply for token + updateTokenInfo($data->TICK); + } +} + +?> \ No newline at end of file diff --git a/indexer/includes/config.php b/indexer/includes/config.php index 3433041..4bf305d 100644 --- a/indexer/includes/config.php +++ b/indexer/includes/config.php @@ -37,9 +37,13 @@ // First block with BTNS transaction define("FIRST_BLOCK",789742); - // BTNS Address + // BTNS Addresses define('BURN_ADDRESS', "1Muhahahahhahahahahahhahahauxh9QX"); define('GAS_ADDRESS', "1BTNSGASK5En7rFurDJ79LQ8CVYo2ecLC8"); + + // Donation Addresses + define('DONATE_ADDRESS_1', "1BTNSGASK5En7rFurDJ79LQ8CVYo2ecLC8"); // Protocol Development + define('DONATE_ADDRESS_2', "1BTNSGASK5En7rFurDJ79LQ8CVYo2ecLC8"); // Community Develoment } // Testnet config @@ -50,6 +54,10 @@ // BTNS Address define('BURN_ADDRESS', "mvCounterpartyXXXXXXXXXXXXXXW24Hef"); define('GAS_ADDRESS', "mvThcDEbeqog2aJ7JNj1FefUPaNdYYGqHt"); + + // Donation Addresses + define('DONATE_ADDRESS_1', "mvThcDEbeqog2aJ7JNj1FefUPaNdYYGqHt"); // Protocol Development + define('DONATE_ADDRESS_2', "mvThcDEbeqog2aJ7JNj1FefUPaNdYYGqHt"); // Community Develoment } // Database Credentials @@ -71,6 +79,7 @@ require_once('protocol_changes.php'); // BTNS Actions +require_once('actions/address.php'); require_once('actions/airdrop.php'); require_once('actions/batch.php'); require_once('actions/bet.php'); diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 30e8b41..9fc454f 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1382,6 +1382,7 @@ function isCryptoAddress( $address=null ){ // Generalized function to invoke BTNS action commands function btnsAction($action=null, $params=null, $data=null, $error=null){ + if($action=='ADDRESS') btnsAddress($params, $data, $error); if($action=='AIRDROP') btnsAirdrop($params, $data, $error); if($action=='BATCH') btnsBatch($params, $data, $error); if($action=='BET') btnsBet($params, $data, $error); @@ -1959,9 +1960,19 @@ function processTransaction($tx=null){ if(in_array($action,array('DEPLOY','MINT','TRANSFER')) && isLegacyBTNSFormat($params)) array_splice($params, 0, 0, 0); - // Support old BRC20/SRC20 actions - if($action=='TRANSFER') $action = 'SEND'; - if($action=='DEPLOY') $action = 'ISSUE'; + // Define ACTION aliases + $aliases = array( + // Old BRC20/SRC20 actions + 'TRANSFER' => 'SEND', + 'DEPLOY' => 'ISSUE', + // Short action aliases + 'ADDR' => 'ADDRESS' + ); + + // Set ACTION for any aliases + foreach($aliases as $alias => $act) + if($action==$alias) + $action = $act; // Define basic BTNS transaction data object $data = (object) array( @@ -2088,8 +2099,46 @@ function printRuntime($seconds){ $ms = explode(".",$seconds)[1]; if($hours>0) $msg .= "{$hours} hours "; if($mins>0) $msg .= "{$mins} minutes "; - if($secs>0) $msg .= "{$secs}.{$ms} seconds"; + if($secs>0||$ms>0) $msg .= "{$secs}.{$ms} seconds"; print "Total Execution time: {$msg}\n"; } +// Create record in `addresses` table +function createAddressOption( $data=null ){ + global $mysqli; + $source_id = createAddress($data->SOURCE); + $tx_hash_id = createTransaction($data->TX_HASH); + $block_index = $mysqli->real_escape_string($data->BLOCK_INDEX); + $status_id = createStatus($data->STATUS); + $tx_index = $mysqli->real_escape_string($data->TX_INDEX); + $fee_preference = $mysqli->real_escape_string($data->FEE_PREFERENCE); + $require_memo = $mysqli->real_escape_string($data->REQUIRE_MEMO); + // Check if record already exists + $results = $mysqli->query("SELECT tx_index FROM addresses WHERE tx_hash_id='{$tx_hash_id}'"); + if($results){ + if($results->num_rows){ + // UPDATE record + $sql = "UPDATE + addresses + SET + fee_preference='{$fee_preference}', + require_memo='{$require_memo}', + source_id='{$source_id}', + block_index='{$block_index}', + tx_index='{$tx_index}', + status_id='{$status_id}' + WHERE + tx_hash_id='{$tx_hash_id}'"; + } else { + // INSERT record + $sql = "INSERT INTO addresses (tx_index, source_id, tx_hash_id, block_index, fee_preference, require_memo, status_id) values ('{$tx_index}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$fee_preference}', '{$require_memo}', '{$status_id}')"; + } + $results = $mysqli->query($sql); + if(!$results) + byeLog('Error while trying to create / update a record in the addresses table'); + } else { + byeLog('Error while trying to lookup record in addresses table'); + } +} + ?> diff --git a/indexer/includes/protocol_changes.php b/indexer/includes/protocol_changes.php index 935a426..4c4bd81 100644 --- a/indexer/includes/protocol_changes.php +++ b/indexer/includes/protocol_changes.php @@ -11,6 +11,7 @@ // Define `ACTION` commands and `ACTIVATION_BLOCK` for each (ALL UPPER case) // BTNS-420 SPEC defines when things are ACTUALLY activated // active here just means active for testing / debugging + 'ADDRESS' => array(0, 10, 0, 9999999, 999999999), 'AIRDROP' => array(0, 10, 0, 9999999, 999999999), 'BATCH' => array(0, 10, 0, 9999999, 999999999), 'BET' => array(0, 10, 0, 9999999, 999999999), diff --git a/indexer/sql/addresses.sql b/indexer/sql/addresses.sql new file mode 100644 index 0000000..ed8b349 --- /dev/null +++ b/indexer/sql/addresses.sql @@ -0,0 +1,16 @@ +DROP TABLE IF EXISTS addresses; +CREATE TABLE addresses ( + tx_index INTEGER UNSIGNED, -- Unique transaction index + source_id INTEGER UNSIGNED, -- id of record in index_addresses table + tx_hash_id INTEGER UNSIGNED, -- id of record in index_transactions + block_index INTEGER UNSIGNED, -- block index of ADDRESS transaction + fee_preference INTEGER UNSIGNED, + require_memo INTEGER UNSIGNED, + status_id INTEGER UNSIGNED -- id of record in index_statuses table +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +CREATE UNIQUE INDEX tx_index ON addresses (tx_index); +CREATE INDEX source_id ON addresses (source_id); +CREATE INDEX tx_hash_id ON addresses (tx_hash_id); +CREATE INDEX block_index ON addresses (block_index); +CREATE INDEX status_id ON addresses (status_id); \ No newline at end of file From b727b84977d51f0d07126b6eaba12133e88c3f07 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 11:23:48 -0800 Subject: [PATCH 17/42] cleanup --- indexer/includes/actions/address.php | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/indexer/includes/actions/address.php b/indexer/includes/actions/address.php index f3c6ffd..012224f 100644 --- a/indexer/includes/actions/address.php +++ b/indexer/includes/actions/address.php @@ -67,30 +67,6 @@ function btnsAddress($params=null, $data=null, $error=null){ // Create record in addresses table createAddressOption($data); - // If this was a valid transaction, then mint any actual supply - if($status=='valid'){ - - // Credit MINT_SUPPLY to source address - if($data->AMOUNT){ - createCredit('MINT', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->AMOUNT, $data->SOURCE); - - // Transfer AMOUNT to DESTINATION address - if($data->DESTINATION){ - createDebit('MINT', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->AMOUNT, $data->SOURCE); - createCredit('MINT', $data->BLOCK_INDEX, $data->TX_HASH, $data->TICK, $data->AMOUNT, $data->DESTINATION); - } - } - - // If this is a reparse, bail out before updating balances and token information - if($reparse) - return; - - // Update balances for addresses - updateBalances([$data->SOURCE, $data->DESTINATION]); - - // Update supply for token - updateTokenInfo($data->TICK); - } } ?> \ No newline at end of file From 3ff9dd9b4f61f7c51711776708969fa5d5790600 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 11:24:47 -0800 Subject: [PATCH 18/42] more cleanup --- indexer/includes/actions/address.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/includes/actions/address.php b/indexer/includes/actions/address.php index 012224f..4becd67 100644 --- a/indexer/includes/actions/address.php +++ b/indexer/includes/actions/address.php @@ -12,7 +12,7 @@ * ********************************************************************/ function btnsAddress($params=null, $data=null, $error=null){ - global $mysqli, $reparse, $addresses, $tickers; + global $mysqli, $reparse; // Define list of known FORMATS $formats = array( From 94e97c8f433ba78a4e55c733c038a0484378c0da Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 18:15:52 -0800 Subject: [PATCH 19/42] `LOCK_MINT` and `LOCK_MAX_MINT` updates - Renamed `LOCK_MINT` param to `LOCK_MAX_MINT` - Added `LOCK_MINT` param to lock against `MINT` command --- docs/actions/ISSUE.md | 13 +++++++------ indexer/includes/actions/issue.php | 21 +++++++++++---------- indexer/includes/actions/mint.php | 8 ++++++++ indexer/includes/functions.php | 10 ++++++++-- indexer/sql/issues.sql | 3 ++- indexer/sql/tokens.sql | 4 +++- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/docs/actions/ISSUE.md b/docs/actions/ISSUE.md index 244722a..a911bdf 100644 --- a/docs/actions/ISSUE.md +++ b/docs/actions/ISSUE.md @@ -14,7 +14,8 @@ This command creates or issues a `BTNS` `token` | `TRANSFER` | String | Address to transfer ownership of the `token` to (owner can perform future actions on token) | | `TRANSFER_SUPPLY` | String | Address to transfer `MINT_SUPPLY` to (mint initial supply and transfer to address) | | `LOCK_SUPPLY` | String | Lock `MAX_SUPPLY` permanently (cannot increase `MAX_SUPPLY`) | -| `LOCK_MINT` | String | Lock `MAX_MINT` permanently (cannot edit `MAX_MINT`) | +| `LOCK_MAX_MINT` | String | Lock `MAX_MINT` permanently (cannot edit `MAX_MINT`) | +| `LOCK_MINT` | String | Lock `token` against `MINT` command | | `LOCK_DESCRIPTION` | String | Lock `token` against `DESCRIPTION` changes | | `LOCK_RUG` | String | Lock `token` against `RUG` command | | `LOCK_SLEEP` | String | Lock `token` against `SLEEP` command | @@ -32,7 +33,7 @@ This command creates or issues a `BTNS` `token` ## Formats ### Version `0` -- `VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_SUPPLY|LOCK_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK` +- `VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT` ### Version `1` - Edit `DESCRIPTION` - `VERSION|TICK|DESCRIPTION` @@ -41,7 +42,7 @@ This command creates or issues a `BTNS` `token` - `VERSION|TICK|MAX_MINT|MINT_SUPPLY|TRANSFER_SUPPLY|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK` ### Version `3` - Edit `LOCK` `PARAMS` -- `VERSION|TICK|LOCK_SUPPLY|LOCK_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK` +- `VERSION|TICK|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT` ### Version `4` - Edit `CALLBACK` `PARAMS` - `VERSION|TICK|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK` @@ -113,7 +114,8 @@ This example issues a TEST token with a max supply of 100, and a maximum mint of - `ISSUE` `TICK` with `MAX_SUPPLY` and `MINT_SUPPLY` set to any non `0` value, to mint supply until `MAX_SUPPLY` is reached (owner can mint beyond `MAX_MINT`) - `ISSUE` `TICK` with `MAX_SUPPLY` and `MAX_MINT` set to any non `0` value, to enable user minting (fair minting) - `ISSUE` `TICK` with `LOCK_SUPPLY` set to `1` to permanently lock `MAX_SUPPLY` -- `ISSUE` `TICK` with `LOCK_MINT` set to `1` to permanently lock `MAX_MINT` +- `ISSUE` `TICK` with `LOCK_MAX_MINT` set to `1` to permanently lock `MAX_MINT` +- `ISSUE` `TICK` with `LOCK_MINT` set to `1` to permanently prevent use of the `MINT` command - `ISSUE` `TICK` with `LOCK_RUG` set to `1` to permanently prevent use of the `RUG` command - `ISSUE` `TICK` with `LOCK_SLEEP` set to `1` to permanently prevent use of the `SLEEP` command - `ISSUE` `TICK` with `LOCK_CALLBACK` set to `1` to permanently lock `CALLBACK_BLOCK`, `CALLBACK_TICK`, and `CALLBACK_AMOUNT` @@ -126,5 +128,4 @@ This example issues a TEST token with a max supply of 100, and a maximum mint of - If `TICK` contains any unicode characters, then `TICK` should be `base64` encoded - `counterparty` `ASSET` and `SUBASSET` names are reserved within the BTNS for use by the `counterparty` owner - `MINT_ADDRESS_MAX` can be used to limit the maximum `TICK` `AMOUNT` that a single address can `MINT` -- `MINT_START_BLOCK` and `MINT_STOP_BLOCK` can be used to determine period(s) when `MINT` transactions are allowed - +- `MINT_START_BLOCK` and `MINT_STOP_BLOCK` can be used to determine period(s) when `MINT` transactions are allowed \ No newline at end of file diff --git a/indexer/includes/actions/issue.php b/indexer/includes/actions/issue.php index 259ba75..b948fd6 100644 --- a/indexer/includes/actions/issue.php +++ b/indexer/includes/actions/issue.php @@ -13,7 +13,8 @@ * - TRANSFER - Address to transfer ownership of the `token` to (owner can perform future actions on token) * - TRANSFER_SUPPLY - Address to transfer `MINT_SUPPLY` to (mint initial supply and transfer to address) * - LOCK_SUPPLY - Lock `MAX_SUPPLY` permanently (cannot increase `MAX_SUPPLY`) - * - LOCK_MINT - Lock `MAX_MINT` permanently (cannot edit `MAX_MINT`) + * - LOCK_MINT - Lock `token` against `MINT` command + * - LOCK_MAX_MINT - Lock `MAX_MINT` permanently (cannot edit `MAX_MINT`) * - LOCK_DESCRIPTION - Lock `token` against `DESCRIPTION` changes * - LOCK_RUG - Lock `token` against `RUG` command * - LOCK_SLEEP - Lock `token` against `SLEEP` command @@ -40,17 +41,17 @@ function btnsIssue( $params=null, $data=null, $error=null){ // Define list of known FORMATS $formats = array( - 0 => 'VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_SUPPLY|LOCK_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK', + 0 => 'VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT', 1 => 'VERSION|TICK|DESCRIPTION', 2 => 'VERSION|TICK|MAX_MINT|MINT_SUPPLY|TRANSFER_SUPPLY|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK', - 3 => 'VERSION|TICK|LOCK_SUPPLY|LOCK_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK', + 3 => 'VERSION|TICK|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT', 4 => 'VERSION|TICK|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK' ); // Define list of AMOUNT and LOCK fields (used in validations) $fieldList = array( 'AMOUNT' => array('MAX_SUPPLY', 'MAX_MINT', 'MINT_SUPPLY', 'CALLBACK_AMOUNT', 'MINT_ADDRESS_MAX', 'MINT_START_BLOCK', 'MINT_STOP_BLOCK'), - 'LOCK' => array('LOCK_SUPPLY', 'LOCK_MINT', 'LOCK_DESCRIPTION', 'LOCK_RUG', 'LOCK_SLEEP', 'LOCK_CALLBACK') + 'LOCK' => array('LOCK_SUPPLY', 'LOCK_MINT', 'LOCK_MAX_MINT', 'LOCK_DESCRIPTION', 'LOCK_RUG', 'LOCK_SLEEP', 'LOCK_CALLBACK') ); /***************************************************************** @@ -139,14 +140,14 @@ function btnsIssue( $params=null, $data=null, $error=null){ // Verify AMOUNT field formats foreach($fieldList['AMOUNT'] as $name){ - $value = $data->{$name}; + $value = $issue->{$name}; if(!$error && isset($value) && !isValidAmountFormat($divisible, $value)) $error = "invalid: {$name} (format)"; } // Verify LOCK field formats foreach($fieldList['LOCK'] as $name){ - $value = $data->{$name}; + $value = $issue->{$name}; if(!$error && isset($value) && !isValidLockValue($value)) $error = "invalid: {$name} (format)"; } @@ -161,8 +162,8 @@ function btnsIssue( $params=null, $data=null, $error=null){ // Verify LOCK fields cannot be changed once enabled/locked foreach($fieldList['LOCK'] as $name){ - $value = $data->{$name}; - if(!$error && isset($value) && !isValidLock($btInfo, $data, $name)) + $value = $issue->{$name}; + if(!$error && isset($value) && !isValidLock($btInfo, $issue, $name)) $error = "invalid: {$name} (locked)"; } @@ -214,8 +215,8 @@ function btnsIssue( $params=null, $data=null, $error=null){ if(!$error && $btInfo && $btnInfo->LOCK_SUPPLY && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY!=$btnInfo->MAX_SUPPLY) $error = 'invalid: MAX_SUPPLY (locked)'; - // Verify MAX_MINT can not be changed if LOCK_MINT is enabled - if(!$error && $btInfo && $btnInfo->LOCK_MINT && isset($data->MAX_MINT) && $data->MAX_MINT!=$btnInfo->MAX_MINT) + // Verify MAX_MINT can not be changed if LOCK_MAX_MINT is enabled + if(!$error && $btInfo && $btnInfo->LOCK_MAX_MINT && isset($data->MAX_MINT) && $data->MAX_MINT!=$btnInfo->MAX_MINT) $error = 'invalid: MAX_MINT (locked)'; // Verify DESCRIPTION is less than or equal to MAX_TOKEN_DESCRIPTION diff --git a/indexer/includes/actions/mint.php b/indexer/includes/actions/mint.php index 041f1d5..106d865 100644 --- a/indexer/includes/actions/mint.php +++ b/indexer/includes/actions/mint.php @@ -67,6 +67,14 @@ function btnsMint($params=null, $data=null, $error=null){ $data->MINT_STOP_BLOCK = ($btInfo) ? $btInfo->MINT_STOP_BLOCK : 0; } + /***************************************************************** + * ACTION Validations + ****************************************************************/ + + // Verify MINT is allowed + if(!$error && isset($btInfo->LOCK_MINT) && $btInfo->LOCK_MINT==1) + $error = "invalid: LOCK_MINT"; + /***************************************************************** * FORMAT Validations ****************************************************************/ diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 9fc454f..31ab4fa 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -247,6 +247,7 @@ function createIssue( $data=null ){ $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; $lock_mint = ($data->LOCK_MINT==1) ? 1 : 0; + $lock_max_mint = ($data->LOCK_MAX_MINT==1) ? 1 : 0; $lock_description = ($data->LOCK_DESCRIPTION==1) ? 1 : 0; $lock_rug = ($data->LOCK_RUG==1) ? 1 : 0; $lock_sleep = ($data->LOCK_SLEEP==1) ? 1 : 0; @@ -281,6 +282,7 @@ function createIssue( $data=null ){ transfer_supply_id='{$transfer_supply_id}', lock_supply='{$lock_supply}', lock_mint='{$lock_mint}', + lock_max_mint='{$lock_max_mint}', lock_description='{$lock_description}', lock_rug='{$lock_rug}', lock_sleep='{$lock_sleep}', @@ -301,7 +303,7 @@ function createIssue( $data=null ){ tx_hash_id='{$tx_hash_id}'"; } else { // INSERT record - $sql = "INSERT INTO issues (tick_id, max_supply, max_mint, decimals, description, mint_supply, transfer_id, transfer_supply_id, lock_supply, lock_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, source_id, tx_hash_id, block_index, tx_index, status_id) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$mint_supply}', '{$transfer_id}', '{$transfer_supply_id}', '{$lock_supply}', '{$lock_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$tx_index}', '{$status_id}')"; + $sql = "INSERT INTO issues (tick_id, max_supply, max_mint, decimals, description, mint_supply, transfer_id, transfer_supply_id, lock_supply, lock_mint, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, source_id, tx_hash_id, block_index, tx_index, status_id) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$mint_supply}', '{$transfer_id}', '{$transfer_supply_id}', '{$lock_supply}', '{$lock_mint}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$tx_index}', '{$status_id}')"; } // print $sql; $results = $mysqli->query($sql); @@ -490,6 +492,7 @@ function createToken( $data=null ){ $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; $lock_mint = ($data->LOCK_MINT==1) ? 1 : 0; + $lock_max_mint = ($data->LOCK_MAX_MINT==1) ? 1 : 0; $lock_description = ($data->LOCK_DESCRIPTION==1) ? 1 : 0; $lock_rug = ($data->LOCK_RUG==1) ? 1 : 0; $lock_sleep = ($data->LOCK_SLEEP==1) ? 1 : 0; @@ -515,6 +518,7 @@ function createToken( $data=null ){ description='{$description}', lock_supply='{$lock_supply}', lock_mint='{$lock_mint}', + lock_max_mint='{$lock_max_mint}', lock_description='{$lock_description}', lock_rug='{$lock_rug}', lock_sleep='{$lock_sleep}', @@ -533,7 +537,7 @@ function createToken( $data=null ){ tick_id='{$tick_id}'"; } else { // INSERT record - $sql = "INSERT INTO tokens (tick_id, max_supply, max_mint, decimals, description, lock_supply, lock_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, owner_id, supply, block_index) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$lock_supply}', '{$lock_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$owner_id}','{$supply}', '{$block_index}')"; + $sql = "INSERT INTO tokens (tick_id, max_supply, max_mint, decimals, description, lock_supply, lock_mint, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, owner_id, supply, block_index) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$lock_supply}', '{$lock_mint}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$owner_id}','{$supply}', '{$block_index}')"; } // print $sql; $results = $mysqli->query($sql); @@ -879,6 +883,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu t1.block_index, t1.lock_supply, t1.lock_mint, + t1.lock_max_mint, t1.lock_description, t1.lock_rug, t1.lock_sleep, @@ -926,6 +931,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu 'OWNER' => $row->owner, 'LOCK_SUPPLY' => $row->lock_supply, 'LOCK_MINT' => $row->lock_mint, + 'LOCK_MAX_MINT' => $row->lock_max_mint, 'LOCK_DESCRIPTION' => $row->lock_description, 'LOCK_RUG' => $row->lock_rug, 'LOCK_SLEEP' => $row->lock_sleep, diff --git a/indexer/sql/issues.sql b/indexer/sql/issues.sql index 742005c..5955a6d 100644 --- a/indexer/sql/issues.sql +++ b/indexer/sql/issues.sql @@ -10,7 +10,8 @@ CREATE TABLE issues ( transfer_id INTEGER UNSIGNED, -- id of record in index_addresses table transfer_supply_id INTEGER UNSIGNED, -- id of record in index_addresses table lock_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY - lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT + lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT + lock_max_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT lock_description TINYINT(1) NOT NULL DEFAULT 0, -- Locks DESCRIPTION lock_rug TINYINT(1) NOT NULL DEFAULT 0, -- Locks RUG lock_sleep TINYINT(1) NOT NULL DEFAULT 0, -- Locks SLEEP diff --git a/indexer/sql/tokens.sql b/indexer/sql/tokens.sql index 74fd91e..1499117 100644 --- a/indexer/sql/tokens.sql +++ b/indexer/sql/tokens.sql @@ -9,7 +9,8 @@ CREATE TABLE tokens ( decimals TINYINT(2), -- 0=non-divisible, 1-18=divisible description VARCHAR(250), -- URL to icon lock_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY - lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT + lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT + lock_max_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT lock_description TINYINT(1) NOT NULL DEFAULT 0, -- Locks DESCRIPTION lock_rug TINYINT(1) NOT NULL DEFAULT 0, -- Locks RUG lock_sleep TINYINT(1) NOT NULL DEFAULT 0, -- Locks SLEEP @@ -30,6 +31,7 @@ CREATE INDEX tick_id ON tokens (tick_id); CREATE INDEX owner_id ON tokens (owner_id); CREATE INDEX lock_supply ON tokens (lock_supply); CREATE INDEX lock_mint ON tokens (lock_mint); +CREATE INDEX lock_max_mint ON tokens (lock_max_mint); CREATE INDEX lock_description ON tokens (lock_description); CREATE INDEX lock_rug ON tokens (lock_rug); CREATE INDEX lock_sleep ON tokens (lock_sleep); From ff9b9d656cd8e609a8683a9c47643d037e224558 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 18:43:54 -0800 Subject: [PATCH 20/42] Renamed `LOCK_SUPPLY` param to `LOCK_MAX_SUPPLY` --- docs/actions/ISSUE.md | 12 ++++++------ indexer/includes/actions/issue.php | 18 +++++++++--------- indexer/includes/functions.php | 18 ++++++++---------- indexer/sql/issues.sql | 2 +- indexer/sql/tokens.sql | 4 ++-- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/docs/actions/ISSUE.md b/docs/actions/ISSUE.md index a911bdf..35c8db9 100644 --- a/docs/actions/ISSUE.md +++ b/docs/actions/ISSUE.md @@ -13,7 +13,7 @@ This command creates or issues a `BTNS` `token` | `MINT_SUPPLY` | String | Amount of token supply to mint in immediately (default:0) | | `TRANSFER` | String | Address to transfer ownership of the `token` to (owner can perform future actions on token) | | `TRANSFER_SUPPLY` | String | Address to transfer `MINT_SUPPLY` to (mint initial supply and transfer to address) | -| `LOCK_SUPPLY` | String | Lock `MAX_SUPPLY` permanently (cannot increase `MAX_SUPPLY`) | +| `LOCK_MAX_SUPPLY` | String | Lock `MAX_SUPPLY` permanently (cannot increase `MAX_SUPPLY`) | | `LOCK_MAX_MINT` | String | Lock `MAX_MINT` permanently (cannot edit `MAX_MINT`) | | `LOCK_MINT` | String | Lock `token` against `MINT` command | | `LOCK_DESCRIPTION` | String | Lock `token` against `DESCRIPTION` changes | @@ -33,7 +33,7 @@ This command creates or issues a `BTNS` `token` ## Formats ### Version `0` -- `VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT` +- `VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT` ### Version `1` - Edit `DESCRIPTION` - `VERSION|TICK|DESCRIPTION` @@ -42,7 +42,7 @@ This command creates or issues a `BTNS` `token` - `VERSION|TICK|MAX_MINT|MINT_SUPPLY|TRANSFER_SUPPLY|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK` ### Version `3` - Edit `LOCK` `PARAMS` -- `VERSION|TICK|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT` +- `VERSION|TICK|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT` ### Version `4` - Edit `CALLBACK` `PARAMS` - `VERSION|TICK|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK` @@ -58,7 +58,7 @@ This example issues a JDOG token ``` bt:ISSUE|0|JDOG|1||||1|||1 -This example issues a JDOG token with MAX_SUPPLY set to 1, Mints 1 token via MINT_SUPPLY, and has LOCK_SUPPLY set to 1 to permanently lock the MAX_SUPPLY +This example issues a JDOG token with MAX_SUPPLY set to 1, Mints 1 token via MINT_SUPPLY, and has LOCK_MAX_SUPPLY set to 1 to permanently lock the MAX_SUPPLY ``` ``` @@ -108,12 +108,12 @@ This example issues a TEST token with a max supply of 100, and a maximum mint of - `DECIMALS` can not be changed after `token` supply is issued and/or minted - `MAX_SUPPLY` max value is 1,000,000,000,000,000,000,000 (1 Sextillion) - `MAX_SUPPLY` can not be set below existing supply -- `LOCK_SUPPLY` can not be set to `1` and permanently locked until `MIN_TOKEN_SUPPLY` supply exists. +- `LOCK_MAX_SUPPLY` can not be set to `1` and permanently locked until `MIN_TOKEN_SUPPLY` supply exists. ## Notes - `ISSUE` `TICK` with `MAX_SUPPLY` and `MINT_SUPPLY` set to any non `0` value, to mint supply until `MAX_SUPPLY` is reached (owner can mint beyond `MAX_MINT`) - `ISSUE` `TICK` with `MAX_SUPPLY` and `MAX_MINT` set to any non `0` value, to enable user minting (fair minting) -- `ISSUE` `TICK` with `LOCK_SUPPLY` set to `1` to permanently lock `MAX_SUPPLY` +- `ISSUE` `TICK` with `LOCK_MAX_SUPPLY` set to `1` to permanently lock `MAX_SUPPLY` - `ISSUE` `TICK` with `LOCK_MAX_MINT` set to `1` to permanently lock `MAX_MINT` - `ISSUE` `TICK` with `LOCK_MINT` set to `1` to permanently prevent use of the `MINT` command - `ISSUE` `TICK` with `LOCK_RUG` set to `1` to permanently prevent use of the `RUG` command diff --git a/indexer/includes/actions/issue.php b/indexer/includes/actions/issue.php index b948fd6..31c6ce6 100644 --- a/indexer/includes/actions/issue.php +++ b/indexer/includes/actions/issue.php @@ -12,7 +12,7 @@ * - MINT_SUPPLY - Amount of token supply to mint in immediately (default:0) * - TRANSFER - Address to transfer ownership of the `token` to (owner can perform future actions on token) * - TRANSFER_SUPPLY - Address to transfer `MINT_SUPPLY` to (mint initial supply and transfer to address) - * - LOCK_SUPPLY - Lock `MAX_SUPPLY` permanently (cannot increase `MAX_SUPPLY`) + * - LOCK_MAX_SUPPLY - Lock `MAX_SUPPLY` permanently (cannot increase `MAX_SUPPLY`) * - LOCK_MINT - Lock `token` against `MINT` command * - LOCK_MAX_MINT - Lock `MAX_MINT` permanently (cannot edit `MAX_MINT`) * - LOCK_DESCRIPTION - Lock `token` against `DESCRIPTION` changes @@ -41,17 +41,17 @@ function btnsIssue( $params=null, $data=null, $error=null){ // Define list of known FORMATS $formats = array( - 0 => 'VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT', + 0 => 'VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT', 1 => 'VERSION|TICK|DESCRIPTION', 2 => 'VERSION|TICK|MAX_MINT|MINT_SUPPLY|TRANSFER_SUPPLY|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK', - 3 => 'VERSION|TICK|LOCK_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT', + 3 => 'VERSION|TICK|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT', 4 => 'VERSION|TICK|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK' ); // Define list of AMOUNT and LOCK fields (used in validations) $fieldList = array( 'AMOUNT' => array('MAX_SUPPLY', 'MAX_MINT', 'MINT_SUPPLY', 'CALLBACK_AMOUNT', 'MINT_ADDRESS_MAX', 'MINT_START_BLOCK', 'MINT_STOP_BLOCK'), - 'LOCK' => array('LOCK_SUPPLY', 'LOCK_MINT', 'LOCK_MAX_MINT', 'LOCK_DESCRIPTION', 'LOCK_RUG', 'LOCK_SLEEP', 'LOCK_CALLBACK') + 'LOCK' => array('LOCK_MAX_SUPPLY', 'LOCK_MINT', 'LOCK_MAX_MINT', 'LOCK_DESCRIPTION', 'LOCK_RUG', 'LOCK_SLEEP', 'LOCK_CALLBACK') ); /***************************************************************** @@ -175,9 +175,9 @@ function btnsIssue( $params=null, $data=null, $error=null){ if(!$error && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY > 0 && $data->MAX_SUPPLY < getTokenSupply($data->TICK, $data->BLOCK_INDEX, $data->TX_INDEX)) $error = 'invalid: MAX_SUPPLY < SUPPLY'; - // Verify SUPPLY is at least MIN_TOKEN_SUPPLY before allowing LOCK_SUPPLY - if(!$error && $data->LOCK_SUPPLY && (($btInfo && $btInfo->SUPPLY < MIN_TOKEN_SUPPLY) || (!$btInfo && $data->MINT_SUPPLY < MIN_TOKEN_SUPPLY))) - $error = 'invalid: LOCK_SUPPLY (no supply)'; + // Verify SUPPLY is at least MIN_TOKEN_SUPPLY before allowing LOCK_MAX_SUPPLY + if(!$error && $data->LOCK_MAX_SUPPLY && (($btInfo && $btInfo->SUPPLY < MIN_TOKEN_SUPPLY) || (!$btInfo && $data->MINT_SUPPLY < MIN_TOKEN_SUPPLY))) + $error = 'invalid: LOCK_MAX_SUPPLY (no supply)'; // Verify DECIMAL min/max if(!$error && isset($data->DECIMALS) && ($data->DECIMALS < MIN_TOKEN_DECIMALS || $data->DECIMALS > MAX_TOKEN_DECIMALS)) @@ -211,8 +211,8 @@ function btnsIssue( $params=null, $data=null, $error=null){ if(!$error && isset($data->MINT_ADDRESS_MAX) && $data->MINT_ADDRESS_MAX > 0 && $data->MINT_ADDRESS_MAX < $data->MAX_MINT) $error = 'invalid: MINT_ADDRESS_MAX < MAX_MINT'; - // Verify MAX_SUPPLY can not be changed if LOCK_SUPPLY is enabled - if(!$error && $btInfo && $btnInfo->LOCK_SUPPLY && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY!=$btnInfo->MAX_SUPPLY) + // Verify MAX_SUPPLY can not be changed if LOCK_MAX_SUPPLY is enabled + if(!$error && $btInfo && $btnInfo->LOCK_MAX_SUPPLY && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY!=$btnInfo->MAX_SUPPLY) $error = 'invalid: MAX_SUPPLY (locked)'; // Verify MAX_MINT can not be changed if LOCK_MAX_MINT is enabled diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 31ab4fa..6fd2b7f 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -244,8 +244,7 @@ function createIssue( $data=null ){ $tx_index = $mysqli->real_escape_string($data->TX_INDEX); $status = $mysqli->real_escape_string($data->STATUS); // Force lock fields to integer values - $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; - $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; + $lock_max_supply = ($data->LOCK_MAX_SUPPLY==1) ? 1 : 0; $lock_mint = ($data->LOCK_MINT==1) ? 1 : 0; $lock_max_mint = ($data->LOCK_MAX_MINT==1) ? 1 : 0; $lock_description = ($data->LOCK_DESCRIPTION==1) ? 1 : 0; @@ -280,7 +279,7 @@ function createIssue( $data=null ){ mint_supply='{$mint_supply}', transfer_id='{$transfer_id}', transfer_supply_id='{$transfer_supply_id}', - lock_supply='{$lock_supply}', + lock_max_supply='{$lock_max_supply}', lock_mint='{$lock_mint}', lock_max_mint='{$lock_max_mint}', lock_description='{$lock_description}', @@ -303,7 +302,7 @@ function createIssue( $data=null ){ tx_hash_id='{$tx_hash_id}'"; } else { // INSERT record - $sql = "INSERT INTO issues (tick_id, max_supply, max_mint, decimals, description, mint_supply, transfer_id, transfer_supply_id, lock_supply, lock_mint, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, source_id, tx_hash_id, block_index, tx_index, status_id) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$mint_supply}', '{$transfer_id}', '{$transfer_supply_id}', '{$lock_supply}', '{$lock_mint}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$tx_index}', '{$status_id}')"; + $sql = "INSERT INTO issues (tick_id, max_supply, max_mint, decimals, description, mint_supply, transfer_id, transfer_supply_id, lock_max_supply, lock_mint, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, source_id, tx_hash_id, block_index, tx_index, status_id) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$mint_supply}', '{$transfer_id}', '{$transfer_supply_id}', '{$lock_max_supply}', '{$lock_mint}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$tx_index}', '{$status_id}')"; } // print $sql; $results = $mysqli->query($sql); @@ -489,8 +488,7 @@ function createToken( $data=null ){ $description = $mysqli->real_escape_string($data->DESCRIPTION); $block_index = $mysqli->real_escape_string($data->BLOCK_INDEX); // Force lock fields to integer values - $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; - $lock_supply = ($data->LOCK_SUPPLY==1) ? 1 : 0; + $lock_max_supply = ($data->LOCK_MAX_SUPPLY==1) ? 1 : 0; $lock_mint = ($data->LOCK_MINT==1) ? 1 : 0; $lock_max_mint = ($data->LOCK_MAX_MINT==1) ? 1 : 0; $lock_description = ($data->LOCK_DESCRIPTION==1) ? 1 : 0; @@ -516,7 +514,7 @@ function createToken( $data=null ){ max_mint='{$max_mint}', decimals='{$decimals}', description='{$description}', - lock_supply='{$lock_supply}', + lock_max_supply='{$lock_max_supply}', lock_mint='{$lock_mint}', lock_max_mint='{$lock_max_mint}', lock_description='{$lock_description}', @@ -537,7 +535,7 @@ function createToken( $data=null ){ tick_id='{$tick_id}'"; } else { // INSERT record - $sql = "INSERT INTO tokens (tick_id, max_supply, max_mint, decimals, description, lock_supply, lock_mint, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, owner_id, supply, block_index) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$lock_supply}', '{$lock_mint}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$owner_id}','{$supply}', '{$block_index}')"; + $sql = "INSERT INTO tokens (tick_id, max_supply, max_mint, decimals, description, lock_max_supply, lock_mint, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, owner_id, supply, block_index) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$lock_max_supply}', '{$lock_mint}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$owner_id}','{$supply}', '{$block_index}')"; } // print $sql; $results = $mysqli->query($sql); @@ -881,7 +879,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu t1.decimals, t1.description, t1.block_index, - t1.lock_supply, + t1.lock_max_supply, t1.lock_mint, t1.lock_max_mint, t1.lock_description, @@ -929,7 +927,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu 'DECIMALS' => $row->decimals, 'DESCRIPTION' => $row->description, 'OWNER' => $row->owner, - 'LOCK_SUPPLY' => $row->lock_supply, + 'LOCK_MAX_SUPPLY' => $row->lock_max_supply, 'LOCK_MINT' => $row->lock_mint, 'LOCK_MAX_MINT' => $row->lock_max_mint, 'LOCK_DESCRIPTION' => $row->lock_description, diff --git a/indexer/sql/issues.sql b/indexer/sql/issues.sql index 5955a6d..8916d1c 100644 --- a/indexer/sql/issues.sql +++ b/indexer/sql/issues.sql @@ -9,7 +9,7 @@ CREATE TABLE issues ( mint_supply VARCHAR(250), -- Maximum amount of supply a MINT transaction can issue transfer_id INTEGER UNSIGNED, -- id of record in index_addresses table transfer_supply_id INTEGER UNSIGNED, -- id of record in index_addresses table - lock_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY + lock_max_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT lock_max_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT lock_description TINYINT(1) NOT NULL DEFAULT 0, -- Locks DESCRIPTION diff --git a/indexer/sql/tokens.sql b/indexer/sql/tokens.sql index 1499117..99558ae 100644 --- a/indexer/sql/tokens.sql +++ b/indexer/sql/tokens.sql @@ -8,7 +8,7 @@ CREATE TABLE tokens ( max_mint VARCHAR(250), -- Supply minted decimals TINYINT(2), -- 0=non-divisible, 1-18=divisible description VARCHAR(250), -- URL to icon - lock_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY + lock_max_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT lock_max_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT lock_description TINYINT(1) NOT NULL DEFAULT 0, -- Locks DESCRIPTION @@ -29,7 +29,7 @@ CREATE TABLE tokens ( CREATE INDEX tick_id ON tokens (tick_id); CREATE INDEX owner_id ON tokens (owner_id); -CREATE INDEX lock_supply ON tokens (lock_supply); +CREATE INDEX lock_max_supply ON tokens (lock_max_supply); CREATE INDEX lock_mint ON tokens (lock_mint); CREATE INDEX lock_max_mint ON tokens (lock_max_mint); CREATE INDEX lock_description ON tokens (lock_description); From bc1affd02caa6244bba02a3a3fb7abd6acb0f3fe Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 8 Mar 2024 19:39:42 -0800 Subject: [PATCH 21/42] Added `LOCK_MINT_SUPPLY` param --- docs/actions/ISSUE.md | 5 +++-- indexer/includes/actions/issue.php | 10 +++++++--- indexer/includes/functions.php | 6 +++++- indexer/sql/issues.sql | 1 + indexer/sql/tokens.sql | 2 ++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/actions/ISSUE.md b/docs/actions/ISSUE.md index 35c8db9..f73d8e8 100644 --- a/docs/actions/ISSUE.md +++ b/docs/actions/ISSUE.md @@ -16,6 +16,7 @@ This command creates or issues a `BTNS` `token` | `LOCK_MAX_SUPPLY` | String | Lock `MAX_SUPPLY` permanently (cannot increase `MAX_SUPPLY`) | | `LOCK_MAX_MINT` | String | Lock `MAX_MINT` permanently (cannot edit `MAX_MINT`) | | `LOCK_MINT` | String | Lock `token` against `MINT` command | +| `LOCK_MINT_SUPPLY` | String | Lock `token` against issuing additional supply via `MINT_SUPPLY` | | `LOCK_DESCRIPTION` | String | Lock `token` against `DESCRIPTION` changes | | `LOCK_RUG` | String | Lock `token` against `RUG` command | | `LOCK_SLEEP` | String | Lock `token` against `SLEEP` command | @@ -33,7 +34,7 @@ This command creates or issues a `BTNS` `token` ## Formats ### Version `0` -- `VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT` +- `VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT|LOCK_MINT_SUPPLY` ### Version `1` - Edit `DESCRIPTION` - `VERSION|TICK|DESCRIPTION` @@ -42,7 +43,7 @@ This command creates or issues a `BTNS` `token` - `VERSION|TICK|MAX_MINT|MINT_SUPPLY|TRANSFER_SUPPLY|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK` ### Version `3` - Edit `LOCK` `PARAMS` -- `VERSION|TICK|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT` +- `VERSION|TICK|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT|LOCK_MINT_SUPPLY` ### Version `4` - Edit `CALLBACK` `PARAMS` - `VERSION|TICK|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK` diff --git a/indexer/includes/actions/issue.php b/indexer/includes/actions/issue.php index 31c6ce6..83f27d9 100644 --- a/indexer/includes/actions/issue.php +++ b/indexer/includes/actions/issue.php @@ -41,17 +41,17 @@ function btnsIssue( $params=null, $data=null, $error=null){ // Define list of known FORMATS $formats = array( - 0 => 'VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT', + 0 => 'VERSION|TICK|MAX_SUPPLY|MAX_MINT|DECIMALS|DESCRIPTION|MINT_SUPPLY|TRANSFER|TRANSFER_SUPPLY|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK|CALLBACK_AMOUNT|ALLOW_LIST|BLOCK_LIST|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK|LOCK_MINT|LOCK_MINT_SUPPLY', 1 => 'VERSION|TICK|DESCRIPTION', 2 => 'VERSION|TICK|MAX_MINT|MINT_SUPPLY|TRANSFER_SUPPLY|MINT_ADDRESS_MAX|MINT_START_BLOCK|MINT_STOP_BLOCK', - 3 => 'VERSION|TICK|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT', + 3 => 'VERSION|TICK|LOCK_MAX_SUPPLY|LOCK_MAX_MINT|LOCK_DESCRIPTION|LOCK_RUG|LOCK_SLEEP|LOCK_CALLBACK|LOCK_MINT|LOCK_MINT_SUPPLY', 4 => 'VERSION|TICK|LOCK_CALLBACK|CALLBACK_BLOCK|CALLBACK_TICK' ); // Define list of AMOUNT and LOCK fields (used in validations) $fieldList = array( 'AMOUNT' => array('MAX_SUPPLY', 'MAX_MINT', 'MINT_SUPPLY', 'CALLBACK_AMOUNT', 'MINT_ADDRESS_MAX', 'MINT_START_BLOCK', 'MINT_STOP_BLOCK'), - 'LOCK' => array('LOCK_MAX_SUPPLY', 'LOCK_MINT', 'LOCK_MAX_MINT', 'LOCK_DESCRIPTION', 'LOCK_RUG', 'LOCK_SLEEP', 'LOCK_CALLBACK') + 'LOCK' => array('LOCK_MAX_SUPPLY', 'LOCK_MINT', 'LOCK_MINT_SUPPLY', 'LOCK_MAX_MINT', 'LOCK_DESCRIPTION', 'LOCK_RUG', 'LOCK_SLEEP', 'LOCK_CALLBACK') ); /***************************************************************** @@ -199,6 +199,10 @@ function btnsIssue( $params=null, $data=null, $error=null){ if(!$error && isset($data->TRANSFER_SUPPLY) && !isCryptoAddress($data->TRANSFER_SUPPLY)) $error = 'invalid: TRANSFER_SUPPLY (bad address)'; + // Verify MINT_SUPPLY is allowed and LOCK_MINT_SUPPLY is not set + if(!$error && isset($data->MINT_SUPPLY) && $btInfo && $btInfo->LOCK_MINT_SUPPLY==1) + $error = 'invalid: MINT_SUPPLY (locked)'; + // Verify MINT_SUPPLY is less than MAX_SUPPLY if(!$error && isset($data->MINT_SUPPLY) && $data->MINT_SUPPLY > $data->MAX_SUPPLY) $error = 'invalid: MINT_SUPPLY > MAX_SUPPLY'; diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 6fd2b7f..4fe562e 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -246,6 +246,7 @@ function createIssue( $data=null ){ // Force lock fields to integer values $lock_max_supply = ($data->LOCK_MAX_SUPPLY==1) ? 1 : 0; $lock_mint = ($data->LOCK_MINT==1) ? 1 : 0; + $lock_mint_supply = ($data->LOCK_MINT_SUPPLY==1) ? 1 : 0; $lock_max_mint = ($data->LOCK_MAX_MINT==1) ? 1 : 0; $lock_description = ($data->LOCK_DESCRIPTION==1) ? 1 : 0; $lock_rug = ($data->LOCK_RUG==1) ? 1 : 0; @@ -281,6 +282,7 @@ function createIssue( $data=null ){ transfer_supply_id='{$transfer_supply_id}', lock_max_supply='{$lock_max_supply}', lock_mint='{$lock_mint}', + lock_mint_supply='{$lock_mint_supply}', lock_max_mint='{$lock_max_mint}', lock_description='{$lock_description}', lock_rug='{$lock_rug}', @@ -302,7 +304,7 @@ function createIssue( $data=null ){ tx_hash_id='{$tx_hash_id}'"; } else { // INSERT record - $sql = "INSERT INTO issues (tick_id, max_supply, max_mint, decimals, description, mint_supply, transfer_id, transfer_supply_id, lock_max_supply, lock_mint, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, source_id, tx_hash_id, block_index, tx_index, status_id) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$mint_supply}', '{$transfer_id}', '{$transfer_supply_id}', '{$lock_max_supply}', '{$lock_mint}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$tx_index}', '{$status_id}')"; + $sql = "INSERT INTO issues (tick_id, max_supply, max_mint, decimals, description, mint_supply, transfer_id, transfer_supply_id, lock_max_supply, lock_mint, lock_mint_supply, lock_max_mint, lock_description, lock_rug, lock_sleep, lock_callback, callback_block, callback_tick_id, callback_amount, allow_list_id, block_list_id, mint_address_max, mint_start_block, mint_stop_block, source_id, tx_hash_id, block_index, tx_index, status_id) values ('{$tick_id}', '{$max_supply}', '{$max_mint}', '{$decimals}', '{$description}', '{$mint_supply}', '{$transfer_id}', '{$transfer_supply_id}', '{$lock_max_supply}', '{$lock_mint}', '{$lock_mint_supply}', '{$lock_max_mint}', '{$lock_description}', '{$lock_rug}', '{$lock_sleep}', '{$lock_callback}', '{$callback_block}', '{$callback_tick_id}', '{$callback_amount}', '{$allow_list_id}', '{$block_list_id}', '{$mint_address_max}', '{$mint_start_block}', '{$mint_stop_block}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$tx_index}', '{$status_id}')"; } // print $sql; $results = $mysqli->query($sql); @@ -880,6 +882,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu t1.description, t1.block_index, t1.lock_max_supply, + t1.lock_mint_supply, t1.lock_mint, t1.lock_max_mint, t1.lock_description, @@ -928,6 +931,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu 'DESCRIPTION' => $row->description, 'OWNER' => $row->owner, 'LOCK_MAX_SUPPLY' => $row->lock_max_supply, + 'LOCK_MINT_SUPPLY' => $row->lock_mint_supply, 'LOCK_MINT' => $row->lock_mint, 'LOCK_MAX_MINT' => $row->lock_max_mint, 'LOCK_DESCRIPTION' => $row->lock_description, diff --git a/indexer/sql/issues.sql b/indexer/sql/issues.sql index 8916d1c..cbcaf82 100644 --- a/indexer/sql/issues.sql +++ b/indexer/sql/issues.sql @@ -11,6 +11,7 @@ CREATE TABLE issues ( transfer_supply_id INTEGER UNSIGNED, -- id of record in index_addresses table lock_max_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT + lock_mint_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT_SUPPLY lock_max_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT lock_description TINYINT(1) NOT NULL DEFAULT 0, -- Locks DESCRIPTION lock_rug TINYINT(1) NOT NULL DEFAULT 0, -- Locks RUG diff --git a/indexer/sql/tokens.sql b/indexer/sql/tokens.sql index 99558ae..9ee27ae 100644 --- a/indexer/sql/tokens.sql +++ b/indexer/sql/tokens.sql @@ -10,6 +10,7 @@ CREATE TABLE tokens ( description VARCHAR(250), -- URL to icon lock_max_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT + lock_mint_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT_SUPPLY lock_max_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT lock_description TINYINT(1) NOT NULL DEFAULT 0, -- Locks DESCRIPTION lock_rug TINYINT(1) NOT NULL DEFAULT 0, -- Locks RUG @@ -32,6 +33,7 @@ CREATE INDEX owner_id ON tokens (owner_id); CREATE INDEX lock_max_supply ON tokens (lock_max_supply); CREATE INDEX lock_mint ON tokens (lock_mint); CREATE INDEX lock_max_mint ON tokens (lock_max_mint); +CREATE INDEX lock_mint_supply ON tokens (lock_mint_supply); CREATE INDEX lock_description ON tokens (lock_description); CREATE INDEX lock_rug ON tokens (lock_rug); CREATE INDEX lock_sleep ON tokens (lock_sleep); From d123757c7fa1eccac08fb8007c495aef0c035658 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Mon, 11 Mar 2024 15:34:45 -0700 Subject: [PATCH 22/42] index updates --- indexer/sql/issues.sql | 1 + indexer/sql/lists.sql | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/indexer/sql/issues.sql b/indexer/sql/issues.sql index cbcaf82..86053b5 100644 --- a/indexer/sql/issues.sql +++ b/indexer/sql/issues.sql @@ -36,6 +36,7 @@ CREATE INDEX tick_id ON issues (tick_id); CREATE INDEX source_id ON issues (source_id); CREATE INDEX transfer_id ON issues (transfer_id); CREATE INDEX transfer_supply_id ON issues (transfer_supply_id); +CREATE INDEX block_index ON issues (block_index); CREATE INDEX status_id ON issues (status_id); CREATE INDEX tx_hash_id ON issues (tx_hash_id); CREATE INDEX callback_tick_id ON issues (callback_tick_id); diff --git a/indexer/sql/lists.sql b/indexer/sql/lists.sql index d8cf673..44e836f 100644 --- a/indexer/sql/lists.sql +++ b/indexer/sql/lists.sql @@ -10,8 +10,14 @@ CREATE TABLE lists ( status_id INTEGER UNSIGNED -- id of record in index_statuses table ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - - +CREATE UNIQUE INDEX tx_index ON lists (tx_index); +CREATE INDEX block_index ON lists (block_index); +CREATE INDEX type ON lists (type); +CREATE INDEX edit ON lists (edit); +CREATE INDEX list_tx_hash_id ON lists (list_tx_hash_id); +CREATE INDEX tx_hash_id ON lists (tx_hash_id); +CREATE INDEX source_id ON lists (source_id); +CREATE INDEX status_id ON lists (status_id); From ac26d37214515db17c793164af8a28a45b38c334 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Mon, 11 Mar 2024 20:30:40 -0700 Subject: [PATCH 23/42] add `BATCH` support --- docs/actions/BATCH.md | 7 ++-- indexer/includes/actions/batch.php | 54 ++++++++++++++++++++++++++++-- indexer/includes/functions.php | 43 ++++++++++++++++++++++-- indexer/sql/batches.sql | 14 ++++++++ 4 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 indexer/sql/batches.sql diff --git a/docs/actions/BATCH.md b/docs/actions/BATCH.md index 2727687..b338a4e 100644 --- a/docs/actions/BATCH.md +++ b/docs/actions/BATCH.md @@ -14,12 +14,15 @@ This command batch executes multiple `BTNS` `ACTION` commands in a single transa ## Examples ``` -bt:BATCH|0|MINT|0|GAS|1000;ISSUE|0|JDOG -This example mints 1000 GAS tokens and reserves the JDOG token +bt:BATCH|0|MINT|0|GAS|60;ISSUE|0|JDOG +This example mints 60 GAS tokens and reserves the JDOG token ``` ## Rules - Can only use one `MINT` command in a `BATCH` command - Can only use one `ISSUE` command in a `BATCH` command +- Can only use one `LIST` command in a `BATCH` command +- Can not use `BATCH` as a command in a `BATCH` command ## Notes +- `COMMANDS` are separated by a semi-colon `;` diff --git a/indexer/includes/actions/batch.php b/indexer/includes/actions/batch.php index 7883748..c53206c 100644 --- a/indexer/includes/actions/batch.php +++ b/indexer/includes/actions/batch.php @@ -11,7 +11,57 @@ ********************************************************************/ function btnsBatch($params=null, $data=null, $error=null){ global $mysqli, $reparse; - // Coming soon + + // Define list of known FORMATS + $formats = array( + 0 => 'VERSION|COMMAND' + ); + + // Clone the raw data for storage in mints table + $batch = clone($data); + + /***************************************************************** + * DEBUGGING - Force params + ****************************************************************/ + // $data->TX_RAW = "BATCH|0|MINT|0|GAS|60;ISSUE|0|JDOGTEST"; + + // Validate that format is known + $format = getFormatVersion($params[0]); + if(!$error && ($format===NULL || !in_array($format,array_keys($formats)))) + $error = 'invalid: VERSION (unknown)'; + + // Get list of commands (after removing BATCH/VERSION) + $commands = explode(';',str_replace('BATCH|0|','',$data->TX_RAW)); + if(!$error && count($commands)==0) + $error = 'invalid: COMMAND (unknown)'; + + /***************************************************************** + * General Validations + ****************************************************************/ + + // Verify all actions are valid + foreach($commands as $command) + if(!$error && !array_key_exists(explode('|',$command)[0],PROTOCOL_CHANGES)) + $error = 'invalid: ACTION (unknown)'; + + // Determine final status + $batch->STATUS = $status = ($error) ? $error : 'valid'; + + // Print status message + print "\n\t BATCH : {$data->SOURCE} : {$batch->STATUS}"; + + // Create record in addresses table + createBatch($batch); + + // Handle processing the specific BTNS ACTION commands + if($status=='valid'){ + foreach($commands as $command){ + $params = explode('|',$command); + $action = strtoupper(array_shift($params)); + btnsAction($action, $params, $data, $error); + } + } + } -?> \ No newline at end of file +?> diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 4fe562e..b53bae4 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1949,7 +1949,8 @@ function processTransaction($tx=null){ $error = false; $tx = (object) $tx; $prefixes = array('/^bt:/','/^btns:/'); - $params = explode('|',preg_replace($prefixes,'',$tx->text)); + $tx->raw = preg_replace($prefixes,'',$tx->text); + $params = explode('|',$tx->raw); $version = $tx->version; // Project Version $source = $tx->source; // Source address @@ -1984,10 +1985,11 @@ function processTransaction($tx=null){ // Define basic BTNS transaction data object $data = (object) array( - 'ACTION' => $action, // Action (ISSUE, MINT, SEND, etc) + 'ACTION' => $action, // Action (ISSUE, MINT, SEND, etc) 'BLOCK_INDEX' => $tx->block_index, // Block index 'SOURCE' => $tx->source, // Source/Broadcasting address - 'TX_HASH' => $tx->tx_hash // Transaction Hash + 'TX_HASH' => $tx->tx_hash, // Transaction Hash + 'TX_RAW' => $tx->raw // Raw TX string ); // Validate Action @@ -2149,4 +2151,39 @@ function createAddressOption( $data=null ){ } } +// Create record in `batches` table +function createBatch( $data=null ){ + global $mysqli; + $source_id = createAddress($data->SOURCE); + $tx_hash_id = createTransaction($data->TX_HASH); + $block_index = $mysqli->real_escape_string($data->BLOCK_INDEX); + $status_id = createStatus($data->STATUS); + $tx_index = $mysqli->real_escape_string($data->TX_INDEX); + // Check if record already exists + $results = $mysqli->query("SELECT tx_index FROM batches WHERE tx_hash_id='{$tx_hash_id}'"); + if($results){ + if($results->num_rows){ + // UPDATE record + $sql = "UPDATE + batches + SET + source_id='{$source_id}', + block_index='{$block_index}', + tx_index='{$tx_index}', + status_id='{$status_id}' + WHERE + tx_hash_id='{$tx_hash_id}'"; + } else { + // INSERT record + $sql = "INSERT INTO batches (tx_index, source_id, tx_hash_id, block_index, status_id) values ('{$tx_index}', '{$source_id}', '{$tx_hash_id}', '{$block_index}', '{$status_id}')"; + } + $results = $mysqli->query($sql); + if(!$results) + byeLog('Error while trying to create / update a record in the batches table'); + } else { + byeLog('Error while trying to lookup record in batches table'); + } +} + + ?> diff --git a/indexer/sql/batches.sql b/indexer/sql/batches.sql new file mode 100644 index 0000000..f01b89c --- /dev/null +++ b/indexer/sql/batches.sql @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS batches; +CREATE TABLE batches ( + tx_index INTEGER UNSIGNED, -- Unique transaction index + source_id INTEGER UNSIGNED, -- id of record in index_addresses table + tx_hash_id INTEGER UNSIGNED, -- id of record in index_transactions + block_index INTEGER UNSIGNED, -- block index of ADDRESS transaction + status_id INTEGER UNSIGNED -- id of record in index_statuses table +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +CREATE UNIQUE INDEX tx_index ON batches (tx_index); +CREATE INDEX source_id ON batches (source_id); +CREATE INDEX tx_hash_id ON batches (tx_hash_id); +CREATE INDEX block_index ON batches (block_index); +CREATE INDEX status_id ON batches (status_id); \ No newline at end of file From 4a0c49a980bd162ff278ebb75fe69c48b1f02943 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 13 Mar 2024 09:02:27 -0700 Subject: [PATCH 24/42] enforce `BATCH` `ACTION` limits --- indexer/includes/actions/batch.php | 39 +++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/indexer/includes/actions/batch.php b/indexer/includes/actions/batch.php index c53206c..9d82d23 100644 --- a/indexer/includes/actions/batch.php +++ b/indexer/includes/actions/batch.php @@ -17,7 +17,17 @@ function btnsBatch($params=null, $data=null, $error=null){ 0 => 'VERSION|COMMAND' ); - // Clone the raw data for storage in mints table + // Define list of ACTIONS and usage limits + $limits = array( + 'BATCH' => 0, + 'MINT' => 1, + 'ISSUE' => 1 + ); + + // Define list of ACTIONS and count of usage within BATCH + $actions = array(); + + // Clone the raw data for storage in batches table $batch = clone($data); /***************************************************************** @@ -30,27 +40,44 @@ function btnsBatch($params=null, $data=null, $error=null){ if(!$error && ($format===NULL || !in_array($format,array_keys($formats)))) $error = 'invalid: VERSION (unknown)'; - // Get list of commands (after removing BATCH/VERSION) - $commands = explode(';',str_replace('BATCH|0|','',$data->TX_RAW)); - if(!$error && count($commands)==0) + // Get list of commands + $commands = explode(';',$data->TX_RAW); + if(!$error && count($commands)==0){ $error = 'invalid: COMMAND (unknown)'; + } else { + // Trim BATCH/VERSION from first command + $commands[0] = str_replace("BATCH|{$format}|",'',$commands[0]); + } + + // Build out array of ACTIONs and count of times used in BATCH + foreach($commands as $command){ + $action = explode('|',$command)[0]; + if(!$actions[$action]) + $actions[$action] = 0; + $actions[$action]++; + } /***************************************************************** * General Validations ****************************************************************/ - // Verify all actions are valid + // Verify all command ACTIONs are valid foreach($commands as $command) if(!$error && !array_key_exists(explode('|',$command)[0],PROTOCOL_CHANGES)) $error = 'invalid: ACTION (unknown)'; + // Verify command ACTION limits + foreach($actions as $action => $limit) + if(!$error && array_key_exists($action,$limits) && $actions[$action]>$limits[$action]) + $error = "invalid: {$action} (limit)"; + // Determine final status $batch->STATUS = $status = ($error) ? $error : 'valid'; // Print status message print "\n\t BATCH : {$data->SOURCE} : {$batch->STATUS}"; - // Create record in addresses table + // Create record in batches table createBatch($batch); // Handle processing the specific BTNS ACTION commands From e734a3427b1f77a6e68b8133b540d8f25af450c8 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 13 Mar 2024 09:16:33 -0700 Subject: [PATCH 25/42] update getTokenInfo to pass forward block/tx_index --- indexer/includes/actions/send.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/includes/actions/send.php b/indexer/includes/actions/send.php index 8081706..5ba304e 100644 --- a/indexer/includes/actions/send.php +++ b/indexer/includes/actions/send.php @@ -84,7 +84,7 @@ function btnsSend($params=null, $data=null, $error=null){ foreach($sends as $send){ $tick = $send[0]; if(!$ticks[$tick]) - $ticks[$tick] = getTokenInfo($tick); + $ticks[$tick] = getTokenInfo($tick, null, $data->BLOCK_INDEX, $data->TX_INDEX); } // Get source address balances From f142921d45f2315a76b582d2c977edace4a61059 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 13 Mar 2024 18:58:42 -0700 Subject: [PATCH 26/42] add detailed format description --- docs/actions/SEND.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/actions/SEND.md b/docs/actions/SEND.md index a047e71..75c5a0b 100644 --- a/docs/actions/SEND.md +++ b/docs/actions/SEND.md @@ -13,16 +13,16 @@ This command sends/transfers one or more `token`s between addresses ## Formats -### Version `0` +### Version `0` - Single Send - `VERSION|TICK|AMOUNT|DESTINATION|MEMO` -### Version `1` +### Version `1` - Multi-Send (Brief) - `VERSION|TICK|AMOUNT|DESTINATION|AMOUNT|DESTINATION|MEMO` -### Version `2` +### Version `2` - Multi-Send (Full) - `VERSION|TICK|AMOUNT|DESTINATION|TICK|AMOUNT|DESTINATION|MEMO` -### Version `3` +### Version `3` - Multi-Send (Full) with Multiple Memos - `VERSION|TICK|AMOUNT|DESTINATION|MEMO|TICK|AMOUNT|DESTINATION|MEMO` From da67f55f47d94fc0208906246a55828884a26279 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 13 Mar 2024 19:15:14 -0700 Subject: [PATCH 27/42] enable protocol_changes version checks --- indexer/includes/functions.php | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index b53bae4..9ffd54a 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1518,13 +1518,10 @@ function isEnabled($name=null, $network=null, $block_index=null){ $mainnet_block_index = $info[3]; $testnet_block_index = $info[4]; $enable_block_index = ${$network . '_block_index'}; - // if(VERSION_MAJOR < $version_major) return false; - // if(VERSION_MINOR < $version_minor) return false; - // if(VERSION_REVISION < $version_revision) return false; - if($block_index >= $enable_block_index) - return true; + if(VERSION_MAJOR >= $version_major && VERSION_MINOR >= $version_minor && VERSION_REVISION >= $version_revision && $block_index >= $enable_block_index) + return 1; } - return false; + return 0; } // Handle returning integer format version @@ -1727,7 +1724,8 @@ function sanityCheck( $block=null ){ // Only perform sanity checks on ACTIONS that are active in protocol_changes if(isEnabled($row->type, $network, $block)){ // Ignore certain tx types - if(in_array($row->type,array('LIST'))) + // TODO: Come back through and get this working with BATCH and AIRDROP commands + if(in_array($row->type,array('LIST','BATCH'))) continue; // Loop through tables and get ticker and supply $table = strtolower($row->type) . 's'; @@ -1946,6 +1944,7 @@ function getBlockHashes($block=null){ // @param {$tx->tx_hash} string Transaction hash // @param {$tx->block_index} string Block index of tx function processTransaction($tx=null){ + global $network; $error = false; $tx = (object) $tx; $prefixes = array('/^bt:/','/^btns:/'); @@ -1993,17 +1992,15 @@ function processTransaction($tx=null){ ); // Validate Action - if(!array_key_exists($action,PROTOCOL_CHANGES)) + if(!array_key_exists($action,PROTOCOL_CHANGES)){ $error = 'invalid: Unknown ACTION'; + $data->ACTION = $action = 'UNKNOWN'; + } // Verify action is activated (past ACTIVATION_BLOCK) - if(!$error && !isEnabled($action, $network, $block)) + if(!$error && !isEnabled($action, $network, $tx->block_index)) $error = 'invalid: ACTIVATION_BLOCK'; - // Set action to UNKNOWN if we detect error - if($error) - $data->ACTION = $action = 'UNKNOWN'; - // Create a record of this transaction in the transactions table createTxIndex($data); From f16ebb2f4afe317221a2c8e5f2f3bf910c760688 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 13 Mar 2024 19:16:23 -0700 Subject: [PATCH 28/42] disable sanity checks for BATCH / AIRDROP --- indexer/includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 9ffd54a..24115e0 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1725,7 +1725,7 @@ function sanityCheck( $block=null ){ if(isEnabled($row->type, $network, $block)){ // Ignore certain tx types // TODO: Come back through and get this working with BATCH and AIRDROP commands - if(in_array($row->type,array('LIST','BATCH'))) + if(in_array($row->type,array('LIST','BATCH','AIRDROP'))) continue; // Loop through tables and get ticker and supply $table = strtolower($row->type) . 's'; From d1fae404108f0f1e79443c7be6d45745d0363ce1 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 13 Mar 2024 19:22:24 -0700 Subject: [PATCH 29/42] add `DROP` alias for `AIRDROP` --- docs/actions/AIRDROP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/actions/AIRDROP.md b/docs/actions/AIRDROP.md index 068bdef..a9069d5 100644 --- a/docs/actions/AIRDROP.md +++ b/docs/actions/AIRDROP.md @@ -39,6 +39,7 @@ This example airdops 1 GAS to every holder on a list and 2 BRRR to every holder ## Rules ## Notes +- `DROP` `ACTION` can be used for shorter reference to `AIRDROP` `ACTION` - `AIRDROP` to `address` `LIST` sends `AMOUNT` of `token` to each address on the list - `AIRDROP` to `token` `LIST` sends `AMOUNT` of `token` to holders of each `token` on the list - `AIRDROP` to `ASSET` `LIST` sends `AMOUNT` of `token` to holders of each `ASSET` on the list From a7a5f62c62530ad707686694a0d6a8f2a147e129 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Thu, 14 Mar 2024 10:48:52 -0700 Subject: [PATCH 30/42] cleanup `sanityCheck()` logic --- indexer/includes/functions.php | 63 ++++++++++------------------------ 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 24115e0..156e2d0 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1706,59 +1706,34 @@ function sanityCheck( $block=null ){ $tickers = []; // Assoc array of tickers $supply = []; // Assoc array of supplys $block_index = $mysqli->real_escape_string($block); - // Get list of tables to check for transactions / tickers - $sql = "SELECT - distinct(t2.type) as type - FROM - transactions t1, - index_tx_types t2 + // Get list of tickers and supply from credits/debits/tokens tables using block_index + $sql = "SELECT + DISTINCT(x.tick_id), + t2.tick, + t1.supply + FROM + ( + SELECT tick_id FROM credits WHERE block_index='{$block_index}' UNION + SELECT tick_id FROM debits WHERE block_index='{$block_index}' + ) as x, + tokens t1, + index_tickers t2 WHERE - t2.id=t1.type_id AND - t2.type!='UNKNOWN' AND - t1.block_index='{$block_index}'"; + t1.tick_id=x.tick_id AND + t2.id=x.tick_id + ORDER BY t2.tick ASC"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ while($row = $results->fetch_assoc()){ $row = (object) $row; - // Only perform sanity checks on ACTIONS that are active in protocol_changes - if(isEnabled($row->type, $network, $block)){ - // Ignore certain tx types - // TODO: Come back through and get this working with BATCH and AIRDROP commands - if(in_array($row->type,array('LIST','BATCH','AIRDROP'))) - continue; - // Loop through tables and get ticker and supply - $table = strtolower($row->type) . 's'; - $sql = "SELECT - t2.id, - t2.tick, - t1.supply - FROM - {$table} m LEFT JOIN tokens t1 on (t1.tick_id=m.tick_id), - index_tickers t2 - WHERE - t2.id=m.tick_id AND - m.block_index='{$block_index}'"; - // print $sql; - $results2 = $mysqli->query($sql); - if($results2){ - if($results2->num_rows){ - while($row2 = $results2->fetch_assoc()){ - $row2 = (object) $row2; - // Add ticker and supply info to assoc arrays - $tickers[$row2->tick] = $row2->id; - $supply[$row2->tick] = (!is_null($row2->supply)) ? $row2->supply : "0"; - } - } - } else { - byeLog("Error while trying to lookup tickers in block : {$block}"); - } - } - + // Add ticker and supply info to assoc arrays + $tickers[$row->tick] = $row->tick_id; + $supply[$row->tick] = (!is_null($row->supply)) ? $row->supply : "0"; } } } else { - byeLog("Error while trying to lookup transactions in block : {$block}"); + byeLog("Error while trying to lookup credits/debits in block : {$block}"); } // Loop through the tickers and validate token supply match credits/debits/balances info foreach($tickers as $tick => $tick_id){ From e654b05030c5a4c0277b86fd19d9099563bb3c69 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 15 Mar 2024 09:42:41 -0700 Subject: [PATCH 31/42] more cleanup - updated `getHolders()` and `isDistributed()` to handle block_index and tx_index - updated `getHolders()` to calculate holder based on credit and debits table instead of balances (credits - debits = balance) --- indexer/includes/actions/issue.php | 2 +- indexer/includes/functions.php | 91 +++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/indexer/includes/actions/issue.php b/indexer/includes/actions/issue.php index 83f27d9..f731b39 100644 --- a/indexer/includes/actions/issue.php +++ b/indexer/includes/actions/issue.php @@ -100,7 +100,7 @@ function btnsIssue( $params=null, $data=null, $error=null){ // Get information on BTNS token $btInfo = getTokenInfo($data->TICK, null, $data->BLOCK_INDEX, $data->TX_INDEX); - $isDistributed = isDistributed($data->TICK); + $isDistributed = isDistributed($data->TICK, $data->BLOCK_INDEX, $data->TX_INDEX); // Clone the raw data for storage in issues table $issue = clone($data); diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 156e2d0..51ba948 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1608,50 +1608,85 @@ function setActionParams($data=null, $params=null, $format=null){ return $data; } -// Handle getting a list of holders -// @param {tick} string TICK or ASSET name -// @param {type} integer Holder Type (1=TICK, 2=ASSET) -function getHolders( $tick=null, $type=null){ +// Handle getting a list of TICK holders and amounts +// @param {tick} string Ticker name +// @param {block_index} integer Block Index +// @param {tx_index} integer tx_index of transaction +function getHolders( $tick=null, $block_index=null, $tx_index=null ){ global $mysqli, $dbase; $holders = []; - $type = ($type>1) ? $type : 1; - $tick = $mysqli->real_escape_string($tick); - // Query TICK Holders - if($type==1){ - $sql = "SELECT - a.address, - b.amount - FROM - balances b, - index_tickers t, - index_addresses a - WHERE - t.id=b.tick_id AND - a.id=b.address_id AND - t.tick='{$tick}'"; - } - // Query ASSET holders - if($type==2){ - // Handle CP ASSETS here... coming soon + $block = (is_numeric($block_index)) ? $block_index : 99999999999999; + $tick_id = createTicker($tick); + // Get info on decimal precision + $decimals = getTokenDecimalPrecision($tick_id); + $whereSql = ""; + // Filter by block_index + if(is_numeric($block)) + $whereSql .= " AND m.block_index <= '{$block}'"; + // Filter by tx_index + if(is_numeric($tx_index)) + $whereSql .= " AND t.tx_index < {$tx_index}"; + // Get Credits + $sql = "SELECT + CAST(SUM(m.amount) AS DECIMAL(60,$decimals)) as credits, + a.address + FROM + credits m, + transactions t, + index_addresses a + WHERE + m.event_id=t.tx_hash_id AND + m.address_id=a.id AND + m.tick_id='{$tick_id}' + {$whereSql} + GROUP BY a.address"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()){ + $row = (object) $row; + $holders[$row->address] = $row->credits; + } + } + } else { + byeLog('Error while trying to get list of credits'); } + // Get Debits + $sql = "SELECT + CAST(SUM(m.amount) AS DECIMAL(60,$decimals)) as debits, + a.address + FROM + debits m, + transactions t, + index_addresses a + WHERE + m.event_id=t.tx_hash_id AND + m.address_id=a.id AND + m.tick_id='{$tick_id}' + {$whereSql} + GROUP BY a.address"; $results = $mysqli->query($sql); if($results){ if($results->num_rows){ while($row = $results->fetch_assoc()){ $row = (object) $row; - $holders[$row->address] = $row->amount; + $balance = bcsub($holders[$row->address], $row->debits, $decimals); + if($balance > 0) + $holders[$row->address] = $balance; + else + unset($holders[$row->address]); } } } else { - byeLog("Error while trying to lookup holders of : {$tick}"); + byeLog('Error while trying to get list of debits'); } return $holders; } // Determine if an ticker is distributed to users (held by more than owner) -function isDistributed($tick=null){ - $info = getTokenInfo($tick); - $holders = ($info) ? getHolders($data->TICK) : []; +function isDistributed($tick=null, $block_index=null, $tx_index=null){ + $info = getTokenInfo($tick, $block_index, $tx_index); + $holders = ($info) ? getHolders($tick, $block_index, $tx_index) : []; // More than one holder if(count($holders)>1) return true; From a7da38f6f15968c7e08a4b2e5d024e0450303186 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 15 Mar 2024 12:55:53 -0700 Subject: [PATCH 32/42] add `AIRDROP` support --- indexer/includes/actions/airdrop.php | 282 ++++++++++++++++++++++++++- indexer/includes/functions.php | 163 +++++++++++++++- indexer/sql/airdrops.sql | 22 +++ indexer/sql/fees.sql | 17 ++ 4 files changed, 478 insertions(+), 6 deletions(-) create mode 100644 indexer/sql/airdrops.sql create mode 100644 indexer/sql/fees.sql diff --git a/indexer/includes/actions/airdrop.php b/indexer/includes/actions/airdrop.php index 4cd83cb..0715ff0 100644 --- a/indexer/includes/actions/airdrop.php +++ b/indexer/includes/actions/airdrop.php @@ -1,20 +1,292 @@ 'VERSION|TICK|AMOUNT|LIST|MEMO', + 1 => 'VERSION|LIST|TICK|AMOUNT|TICK|AMOUNT|MEMO', + 2 => 'VERSION|TICK|AMOUNT|LIST|TICK|AMOUNT|LIST|MEMO', + 3 => 'VERSION|TICK|AMOUNT|LIST|MEMO|TICK|AMOUNT|LIST|MEMO' + ); + + /***************************************************************** + * DEBUGGING - Force params + ****************************************************************/ + // $str = '0|AIRDROPTEST1|1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|test'; // ADDRESS LIST + // $str = '0|AIRDROPTEST2|1|55cd98493c0fe46aed95225d909a82793a9ba7b480dccdb3170a9cd1ce081093|test'; // TICK LIST + // $str = '0|AIRDROPTEST3|1|afd33c2042cd43b229a44c406f03bcc940702f9736f5a222dfa53295b641a00d|test'; // ASSET LIST + // $params = explode('|',$str); + + // Validate that broadcast format is known + $format = getFormatVersion($params[0]); + if(!$error && ($format===NULL || !in_array($format,array_keys($formats)))) + $error = 'invalid: VERSION (unknown)'; + + // Array of airdrops [TICK, AMOUNT, LIST, MEMO] + $airdrops = array(); + + // Extract memo + $memo = NULL; + $last = count($params) - 1; + foreach($params as $idx => $param) + if($idx==$last && (($format==0 && $idx==4) || ($format==1 && $idx%2==0) || ($format==2 && $idx%3==1))) + $memo = $param; + + // Build out array of airdrops + $lastIdx = count($params) - 1; + foreach($params as $idx => $param){ + + // Single Airdrop + if($format==0 && $idx==0) + array_push($airdrops,[$params[1], $params[2], $params[3], $memo]); + + // Multi-Airdrop (brief) + if($format==1 && $idx>1 && $idx%2==1) + array_push($airdrops,[$params[1], $params[$idx-1], $params[$idx], $memo]); + + // Multi-Airdrop (Full) + if($format==2 && $idx>0 && $idx%3==1 && $idx < $lastIdx) + array_push($airdrops,[$params[$idx], $params[$idx+1], $params[$idx+2], $memo]); + + // Multi-Airdrop (Full) with Multiple Memos + if($format==3 && $idx>0 && $idx%4==1 && $idx < $lastIdx) + array_push($airdrops,[$params[$idx], $params[$idx+1], $params[$idx+2], $params[$idx+3]]); + } + + // Get token data for every TICK (reduces duplicated sql queries) + $ticks = []; + foreach($airdrops as $airdrop){ + $tick = $airdrop[0]; + if(!$ticks[$tick]) + $ticks[$tick] = getTokenInfo($tick, null, $data->BLOCK_INDEX, $data->TX_INDEX); + } + + // Get source address balances + $balances = getAddressBalances($data->SOURCE, null, $data->BLOCK_INDEX, $data->TX_INDEX); + + // Get SOURCE address preferences + $preferences = getAddressPreferences($data->SOURCE, $data->BLOCK_INDEX, $data->TX_INDEX); + + // Store original error value + $origError = $error; + + // Array of credits and debits + $credits = []; + $debits = []; + + // Copy base BTNS transaction data object into fees object + $fees = clone($data); + $fees->TICK = 'GAS'; + $fees->AMOUNT = 0; + $fees->METHOD = ($preferences->FEE_PREFERENCE==1) ? 1 : 2; // 1=Destroy, 2=Donate + + // Loop through airdrops and process each + foreach($airdrops as $info){ + + // Reset $error to the original value + $error = $origError; + + // Copy base BTNS Transacation data object + $airdrop = clone($data); + + // Array of addresses that will receive this AIRDROP + $recipients = []; + + // Update BTNS transaction data object with send values + $airdrop->TICK = $info[0]; + $airdrop->AMOUNT = $info[1]; + $airdrop->LIST = $info[2]; + $airdrop->MEMO = $info[3]; + + // Get information on BTNS token + $btInfo = $ticks[$airdrop->TICK]; + + // Set divisible flag + $divisible = ($btInfo->DECIMALS==0) ? 0 : 1; + + // Validate TICK exists + if(!$error && !$btInfo) + $error = 'invalid: TICK (unknown)'; + + /************************************************************* + * FORMAT Validations + ************************************************************/ + + // Verify AMOUNT format + if(!$error && isset($airdrop->AMOUNT) && !isValidAmountFormat($divisible, $airdrop->AMOUNT)) + $error = "invalid: AMOUNT (format)"; + + // Verify LIST format + if(!$error && isset($airdrop->LIST) && !isValidTransactionHash($airdrop->LIST)) + $error = "invalid: LIST (format)"; + + /************************************************************* + * General Validations + ************************************************************/ + + // Verify no pipe in MEMO (BTNS uses pipe as field delimiter) + if(!$error && strpos($airdrop->MEMO,'|')!==false) + $error = 'invalid: MEMO (pipe)'; + + // Verify no semicolon in MEMO (BTNS uses semicolon as action delimiter) + if(!$error && strpos($airdrop->MEMO,';')!==false) + $error = 'invalid: MEMO (semicolon)'; + + // Lookup list information + if(!$error){ + $type = getListType($airdrop->LIST); + $list = getList($airdrop->LIST); + } + + // Verify LIST exist + if(!$error && $type===false) + $error = 'invalid: LIST (unknown)'; + + // Verify LIST type is supported (TICK and ADDRESS only for now) + if(!$error && !in_array($type,array(1,3))) + $error = 'invalid: LIST TYPE (unsupported)'; + + // Handle ADDRESS LIST by passing forward addresses to recipients list + if(!$error && $type==3) + $recipients = $list; + + // Handle TICK LIST by looking up holders and adding to recipients list + if(!$error && $type==1){ + foreach($list as $tick){ + $holders = getHolders($tick, $data->BLOCK_INDEX, $data->TX_INDEX); + foreach($holders as $address => $amount){ + if(!in_array($address, $recipients)) + array_push($recipients, $address); + } + } + } + + // Determine total DEBIT + $airdrop->DEBIT = bcmul(count($recipients),$airdrop->AMOUNT,$btInfo->DECIMALS); + + // Calculate total number of database hits for this AIRDROP + $db_hits = count($recipients) * 2; // 1 credits, 1 balances + $db_hits += 4; // 1 debits, 1 balances, 1 airdrops + + // Determine total transaction FEE based on database hits + $airdrop->FEE_TICK = 'GAS'; + $airdrop->FEE_AMOUNT = getTransactionFee($db_hits, $airdrop->FEE_TICK); + + // Verify SOURCE has enough balances to cover TICK total DEBIT amount + if(!$error && !hasBalance($balances, $airdrop->TICK, $airdrop->DEBIT)) + $error = 'invalid: insufficient funds (TICK)'; + + // Adjust balances to reduce by DEBIT amount + if(!$error) + $balances = debitBalances($balances, $airdrop->TICK, $airdrop->DEBIT); + + // Verify SOURCE has enough balances to cover FEE AMOUNT + if(!$error && !hasBalance($balances, $airdrop->FEE_TICK, $airdrop->FEE_AMOUNT)) + $error = 'invalid: insufficient funds (FEE)'; + + // Adjust balances to reduce by FEE amount + if(!$error) + $balances = debitBalances($balances, $airdrop->TICK, $airdrop->DEBIT); + + // Determine final status + $airdrop->STATUS = $status = ($error) ? $error : 'valid'; + + // Print status message + print "\n\t AIRDROP : {$airdrop->TICK} : {$airdrop->AMOUNT} : {$airdrop->LIST} : {$airdrop->STATUS}"; + + // Create record in airdrops table + createAirdrop($airdrop); + + // If this was a valid transaction, then add records to the credits and debits array + if($status=='valid'){ + + // Store the SOURCE and TICK in addresses list + addAddressTicker($airdrop->SOURCE, [$airdrop->TICK, $airdrop->FEE_TICK]); + + // Debit SOURCE with total DEBIT and FEE_AMOUNT + array_push($debits, array($airdrop->TICK, $airdrop->DEBIT)); + array_push($debits, array($airdrop->FEE_TICK, $airdrop->FEE_AMOUNT)); + + // Update FEES object with to AMOUNT + $fees->AMOUNT = bcadd($fees->AMOUNT, $airdrop->FEE_AMOUNT, 8); + + // Handle using FEE according the the users ADDRESS preferences + if($preferences->FEE_PREFERENCE>1){ + + // Determine what address to donate to + $address = ($preferences->FEE_PREFERENCE==2) ? DONATE_ADDRESS_1 : DONATE_ADDRESS_2; + + // Update the $fees object with the destination address + $fees->DESTINATION = $address; + + // Store the donation ADDRESS and TICK in addresses list + addAddressTicker($address, $airdrop->FEE_TICK); + + // Credit donation address with FEE_AMOUNT + array_push($credits, array($airdrop->FEE_TICK, $airdrop->FEE_AMOUNT, $address)); + } + + // Loop through recipient addresses + foreach($recipients as $address){ + + // Store the recipient ADDRESS and TICK in addresses list + addAddressTicker($address, $airdrop->TICK); + + // Credit address with TICK AMOUNT + array_push($credits, array($airdrop->TICK, $airdrop->AMOUNT, $address)); + } + } + } + + // Consolidate the credit and debit records to write as few records as possible + $debits = consolidateCreditDebitRecords('debits', $debits); + $credits = consolidateCreditDebitRecords('credits', $credits); + + // Create records in debits table + foreach($debits as $debit){ + [$tick, $amount] = $debit; + createDebit('AIRDROP', $data->BLOCK_INDEX, $data->TX_HASH, $tick, $amount, $data->SOURCE); + } + + // Create records in credits table + foreach($credits as $credit){ + [$tick, $amount, $destination] = $credit; + createCredit('AIRDROP', $data->BLOCK_INDEX, $data->TX_HASH, $tick, $amount, $destination); + } + + // Create record of FEE in `fees` table + createFeeRecord($fees); + + // If this is a reparse, bail out before updating balances + if($reparse) + return; + + // Store the SOURCE and TICKERS in addresses list + addAddressTicker($data->SOURCE, $tickers); + + // Update address balances + updateBalances(array_keys($addresses)); + + // Update supply for tokens + updateTokens($tickers); } ?> \ No newline at end of file diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 51ba948..ee896dc 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -2095,7 +2095,14 @@ function addAddressTicker($address=null, $tick=null){ $list = (isset($addresses[$address])) ? $addresses[$address] : []; // If $tick is an array, use the array if($type=="array"){ - $list = $tick; + foreach($tick as $t){ + // Add TICK to $addresses + if(!in_array($t, $list)) + array_push($list, $t); + // Add TICK to $tickers + if(!in_array($t, $tickers)) + array_push($tickers, $t); + } } else { // Add TICK to $addresses if(!in_array($tick, $list)) @@ -2192,5 +2199,159 @@ function createBatch( $data=null ){ } } +// Determine if a tx hash is valid or not +function isValidTransactionHash($hash=null){ + if(strlen($hash)==64) + return 1; + return 0; +} + +// Create record in `airdrops` table +function createAirdrop( $data=null ){ + global $mysqli; + $tick_id = createTicker($data->TICK); + $source_id = createAddress($data->SOURCE); + $tx_hash_id = createTransaction($data->TX_HASH); + $list_id = createMemo($data->LIST); + $memo_id = createMemo($data->MEMO); + $status_id = createStatus($data->STATUS); + $tx_index = $mysqli->real_escape_string($data->TX_INDEX); + $amount = $mysqli->real_escape_string($data->AMOUNT); + $block_index = $mysqli->real_escape_string($data->BLOCK_INDEX); + // Check if record already exists + $sql = "SELECT + tx_index + FROM + airdrops + WHERE + tick_id='{$tick_id}' AND + source_id='{$source_id}' AND + list_id='{$list_id}' AND + amount='{$amount}' AND + tx_hash_id='{$tx_hash_id}'"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + // UPDATE record + $sql = "UPDATE + airdrops + SET + tx_index='{$tx_index}', + block_index='{$block_index}', + memo_id='{$memo_id}', + status_id='{$status_id}' + WHERE + tick_id='{$tick_id}' AND + source_id='{$source_id}' AND + list_id='{$list_id}' AND + amount='{$amount}' AND + tx_hash_id='{$tx_hash_id}'"; + } else { + // INSERT record + $sql = "INSERT INTO airdrops (tx_index, tick_id, source_id, list_id, amount, memo_id, tx_hash_id, block_index, status_id) values ('{$tx_index}','{$tick_id}', '{$source_id}', '{$list_id}', '{$amount}','{$memo_id}', '{$tx_hash_id}', '{$block_index}', '{$status_id}')"; + } + $results = $mysqli->query($sql); + if(!$results) + byeLog('Error while trying to create / update a record in the airdrops table'); + } else { + byeLog('Error while trying to lookup record in airdrops table'); + } +} + + +// Get address preferences for a given address +function getAddressPreferences($address=null, $block_index=null, $tx_index=null){ + global $mysqli; + $address_id = createAddress($address); + // Set default address preferences + $data = (object)[ + 'FEE_PREFERENCE' => 2, // 2=Donate FEES to development + 'REQUIRE_MEMO' => 0 // Require memo on SENDs to this address + ]; + // Get users ADDRESS preferences right before this tx + $whereSql = ""; + if(isset($block_index) && is_numeric($block_index)) + $whereSql .= " AND block_index <= {$block_index}"; + if(isset($tx_index) && is_numeric($tx_index)) + $whereSql .= " AND tx_index < '{$tx_index}'"; + $sql = "SELECT + fee_preference, + require_memo + FROM + addresses a + WHERE + source_id='{$address_id}' + {$whereSql} + ORDER BY tx_index DESC + LIMIT 1"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + $row = (object) $results->fetch_assoc(); + $data->FEE_PREFERENCE = $row->fee_preference; + $data->REQUIRE_MEMO = $row->require_memo; + } + } else { + byeLog('Error while trying to lookup record in addresses table'); + } + return $data; +} + +// Calculate Transaction fee based on number of database hits +// TODO: Make this code modular, so we can configure fees on actions on a per-chain basis +function getTransactionFee($db_hits=0){ + $cost = 10000; // Cost in sats per DB hit + $sats = bcmul($db_hits, $cost , 0); // FEE in sats (integer) + $fee = bcmul($sats, '0.00000001', 8); // FEE in decimal (divisible) + return $fee; +} + +// Create record in `fees` table +function createFeeRecord( $data=null ){ + global $mysqli; + $tick_id = createTicker($data->TICK); + $source_id = createAddress($data->SOURCE); + $destination_id = createAddress($data->DESTINATION); + $tx_index = $mysqli->real_escape_string($data->TX_INDEX); + $amount = $mysqli->real_escape_string($data->AMOUNT); + $method = $mysqli->real_escape_string($data->METHOD); + $block_index = $mysqli->real_escape_string($data->BLOCK_INDEX); + // Check if record already exists + $sql = "SELECT + tx_index + FROM + fees + WHERE + tx_index='{$tx_index}'"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + // UPDATE record + $sql = "UPDATE + fees + SET + tick_id='{$tick_id}', + source_id='{$source_id}', + destination_id='{$destination_id}', + amount='{$amount}', + method='{$method}', + block_index='{$block_index}' + WHERE + tx_index='{$tx_index}'"; + } else { + // INSERT record + $sql = "INSERT INTO fees (tx_index, block_index, source_id, tick_id, amount, method, destination_id) values ('{$tx_index}', '{$block_index}', '{$source_id}', '{$tick_id}', '{$amount}', '{$method}', '{$destination_id}')"; + } + $results = $mysqli->query($sql); + if(!$results) + byeLog('Error while trying to create / update a record in the fees table'); + } else { + byeLog('Error while trying to lookup record in fees table'); + } +} + + + + ?> diff --git a/indexer/sql/airdrops.sql b/indexer/sql/airdrops.sql new file mode 100644 index 0000000..82d40e1 --- /dev/null +++ b/indexer/sql/airdrops.sql @@ -0,0 +1,22 @@ +DROP TABLE IF EXISTS airdrops; +CREATE TABLE airdrops ( + tx_index INTEGER UNSIGNED, -- Unique transaction index + tx_hash_id INTEGER UNSIGNED, -- id of record in index_transactions + block_index INTEGER UNSIGNED, -- block index of AIRDROP transaction + tick_id INTEGER UNSIGNED, -- id of record in index_ticks + source_id INTEGER UNSIGNED, -- id of record in index_addresses table + list_id INTEGER UNSIGNED, -- id of record in index_transactions + amount VARCHAR(250), -- Amount of token in airdrop + memo_id INTEGER UNSIGNED, -- id of record in index_memos table + status_id INTEGER UNSIGNED -- id of record in index_statuses table +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +CREATE INDEX tx_index ON airdrops (tx_index); +CREATE INDEX source_id ON airdrops (source_id); +CREATE INDEX tx_hash_id ON airdrops (tx_hash_id); +CREATE INDEX block_index ON airdrops (block_index); +CREATE INDEX list_id ON airdrops (list_id); +CREATE INDEX tick_id ON airdrops (tick_id); +CREATE INDEX memo_id ON airdrops (memo_id); +CREATE INDEX status_id ON airdrops (status_id); + diff --git a/indexer/sql/fees.sql b/indexer/sql/fees.sql new file mode 100644 index 0000000..91ae260 --- /dev/null +++ b/indexer/sql/fees.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS fees; +CREATE TABLE fees ( + tx_index INTEGER UNSIGNED NOT NULL, -- Unique transaction index + block_index INTEGER UNSIGNED, -- block index of transaction + source_id INTEGER UNSIGNED, -- id of record in index_addresses table + tick_id INTEGER UNSIGNED, -- id of record in index_tickers (default = GAS) + amount VARCHAR(250), -- Amount of TICK + method INTEGER UNSIGNED NOT NULL, -- FEE Payment Method (1=Destroy, 2=Donate) + destination_id INTEGER UNSIGNED -- id of record in index_addresses table +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +CREATE INDEX tx_index ON fees (tx_index); +CREATE INDEX block_index ON fees (block_index); +CREATE INDEX source_id ON fees (source_id); +CREATE INDEX tick_id ON fees (tick_id); +CREATE INDEX destination_id ON fees (destination_id); + From e70a9983f8c7d43ae3aadfa91d0aecce3c064191 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 15 Mar 2024 12:56:18 -0700 Subject: [PATCH 33/42] update rollback to support new tables --- indexer/includes/rollback.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indexer/includes/rollback.php b/indexer/includes/rollback.php index c1eff16..2b41041 100644 --- a/indexer/includes/rollback.php +++ b/indexer/includes/rollback.php @@ -8,10 +8,13 @@ function btnsRollback($block_index=null){ $block_index = (int) $block_index; $tables = [ + 'addresses', + 'batches', 'blocks', 'credits', 'debits', 'destroys', + 'fees', 'issues', 'lists', 'mints', From 1f513c4f512fcee14b76142009f53c2b104b2634 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 15 Mar 2024 12:56:32 -0700 Subject: [PATCH 34/42] cleanup --- indexer/sql/batches.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/sql/batches.sql b/indexer/sql/batches.sql index f01b89c..b79b4d1 100644 --- a/indexer/sql/batches.sql +++ b/indexer/sql/batches.sql @@ -3,7 +3,7 @@ CREATE TABLE batches ( tx_index INTEGER UNSIGNED, -- Unique transaction index source_id INTEGER UNSIGNED, -- id of record in index_addresses table tx_hash_id INTEGER UNSIGNED, -- id of record in index_transactions - block_index INTEGER UNSIGNED, -- block index of ADDRESS transaction + block_index INTEGER UNSIGNED, -- block index of BATCH transaction status_id INTEGER UNSIGNED -- id of record in index_statuses table ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; From 704cf962046fe7a1f5ef4026360994c3bc06f0e9 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Mon, 18 Mar 2024 12:00:22 -0700 Subject: [PATCH 35/42] support for asset lists / fees tweaks - add support for `AIRDROP` to asset `LIST` - cleanup airdrop code so `fees` record is only created on success - add support for `airdrops` table to rollbacks - increased DB hit cost to 10000 --- indexer/includes/actions/airdrop.php | 29 ++++++------ indexer/includes/functions.php | 67 +++++++++++++++++++++++++++- indexer/includes/rollback.php | 1 + 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/indexer/includes/actions/airdrop.php b/indexer/includes/actions/airdrop.php index 0715ff0..0a9458a 100644 --- a/indexer/includes/actions/airdrop.php +++ b/indexer/includes/actions/airdrop.php @@ -30,7 +30,7 @@ function btnsAirdrop($params=null, $data=null, $error=null){ /***************************************************************** * DEBUGGING - Force params ****************************************************************/ - // $str = '0|AIRDROPTEST1|1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|test'; // ADDRESS LIST + // $str = '0|AIRDROPTEST1|1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|test'; // ADDRESS LIST // $str = '0|AIRDROPTEST2|1|55cd98493c0fe46aed95225d909a82793a9ba7b480dccdb3170a9cd1ce081093|test'; // TICK LIST // $str = '0|AIRDROPTEST3|1|afd33c2042cd43b229a44c406f03bcc940702f9736f5a222dfa53295b641a00d|test'; // ASSET LIST // $params = explode('|',$str); @@ -160,18 +160,17 @@ function btnsAirdrop($params=null, $data=null, $error=null){ if(!$error && $type===false) $error = 'invalid: LIST (unknown)'; - // Verify LIST type is supported (TICK and ADDRESS only for now) - if(!$error && !in_array($type,array(1,3))) + // Verify LIST type is supported + if(!$error && !in_array($type,array(1,2,3))) $error = 'invalid: LIST TYPE (unsupported)'; - // Handle ADDRESS LIST by passing forward addresses to recipients list - if(!$error && $type==3) - $recipients = $list; - - // Handle TICK LIST by looking up holders and adding to recipients list - if(!$error && $type==1){ + // Handle ASSET / TICK LIST by looking up holders and adding to recipients list + if(!$error && in_array($type,array(1,2))){ foreach($list as $tick){ - $holders = getHolders($tick, $data->BLOCK_INDEX, $data->TX_INDEX); + if($type==1) + $holders = getHolders($tick, $data->BLOCK_INDEX, $data->TX_INDEX); + if($type==2) + $holders = getAssetHolders($tick, $data->BLOCK_INDEX); foreach($holders as $address => $amount){ if(!in_array($address, $recipients)) array_push($recipients, $address); @@ -179,6 +178,10 @@ function btnsAirdrop($params=null, $data=null, $error=null){ } } + // Handle ADDRESS LIST by passing forward addresses to recipients list + if(!$error && $type==3) + $recipients = $list; + // Determine total DEBIT $airdrop->DEBIT = bcmul(count($recipients),$airdrop->AMOUNT,$btInfo->DECIMALS); @@ -244,6 +247,9 @@ function btnsAirdrop($params=null, $data=null, $error=null){ array_push($credits, array($airdrop->FEE_TICK, $airdrop->FEE_AMOUNT, $address)); } + // Create record of FEE in `fees` table + createFeeRecord($fees); + // Loop through recipient addresses foreach($recipients as $address){ @@ -272,9 +278,6 @@ function btnsAirdrop($params=null, $data=null, $error=null){ createCredit('AIRDROP', $data->BLOCK_INDEX, $data->TX_HASH, $tick, $amount, $destination); } - // Create record of FEE in `fees` table - createFeeRecord($fees); - // If this is a reparse, bail out before updating balances if($reparse) return; diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index ee896dc..4358244 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1683,6 +1683,71 @@ function getHolders( $tick=null, $block_index=null, $tx_index=null ){ return $holders; } +// Handle getting a list of ASSET holders and amounts +// @param {asset} string Asset name +// @param {block_index} integer Block Index +function getAssetHolders( $asset=null, $block_index=null ){ + global $mysqli, $dbase; + $holders = []; + $block = (is_numeric($block_index)) ? $block_index : 99999999999999; + $asset_id = getAssetId($asset); + // Filter by block_index + if(is_numeric($block)) + $whereSql .= " AND m.block_index <= '{$block}'"; + // Get Credits + $sql = "SELECT + CAST(SUM(m.quantity) AS DECIMAL(60,0)) as credits, + a.address + FROM + {$dbase}.credits m, + {$dbase}.index_addresses a + WHERE + m.address_id=a.id AND + m.asset_id='{$asset_id}' + {$whereSql} + GROUP BY a.address"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()){ + $row = (object) $row; + $holders[$row->address] = $row->credits; + } + } + } else { + byeLog('Error while trying to get list of credits'); + } + // Get Debits + $sql = "SELECT + CAST(SUM(m.quantity) AS DECIMAL(60,0)) as debits, + a.address + FROM + {$dbase}.debits m, + {$dbase}.index_addresses a + WHERE + m.address_id=a.id AND + m.asset_id='{$asset_id}' + {$whereSql} + GROUP BY a.address"; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()){ + $row = (object) $row; + $balance = bcsub($holders[$row->address], $row->debits, 0); + if($balance > 0) + $holders[$row->address] = $balance; + else + unset($holders[$row->address]); + } + } + } else { + byeLog('Error while trying to get list of debits'); + } + return $holders; +} + + // Determine if an ticker is distributed to users (held by more than owner) function isDistributed($tick=null, $block_index=null, $tx_index=null){ $info = getTokenInfo($tick, $block_index, $tx_index); @@ -2300,7 +2365,7 @@ function getAddressPreferences($address=null, $block_index=null, $tx_index=null) // Calculate Transaction fee based on number of database hits // TODO: Make this code modular, so we can configure fees on actions on a per-chain basis function getTransactionFee($db_hits=0){ - $cost = 10000; // Cost in sats per DB hit + $cost = 1000; // Cost in sats per DB hit $sats = bcmul($db_hits, $cost , 0); // FEE in sats (integer) $fee = bcmul($sats, '0.00000001', 8); // FEE in decimal (divisible) return $fee; diff --git a/indexer/includes/rollback.php b/indexer/includes/rollback.php index 2b41041..009f04e 100644 --- a/indexer/includes/rollback.php +++ b/indexer/includes/rollback.php @@ -8,6 +8,7 @@ function btnsRollback($block_index=null){ $block_index = (int) $block_index; $tables = [ + 'airdrops', 'addresses', 'batches', 'blocks', From 7150df2e07b0755717cc0be31affe0a89b4968bc Mon Sep 17 00:00:00 2001 From: J-Dog Date: Mon, 18 Mar 2024 12:01:06 -0700 Subject: [PATCH 36/42] add ADDRESS / AIRDROP / BATCH activation blocks --- indexer/includes/protocol_changes.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indexer/includes/protocol_changes.php b/indexer/includes/protocol_changes.php index 4c4bd81..6c74ce7 100644 --- a/indexer/includes/protocol_changes.php +++ b/indexer/includes/protocol_changes.php @@ -11,9 +11,9 @@ // Define `ACTION` commands and `ACTIVATION_BLOCK` for each (ALL UPPER case) // BTNS-420 SPEC defines when things are ACTUALLY activated // active here just means active for testing / debugging - 'ADDRESS' => array(0, 10, 0, 9999999, 999999999), - 'AIRDROP' => array(0, 10, 0, 9999999, 999999999), - 'BATCH' => array(0, 10, 0, 9999999, 999999999), + 'ADDRESS' => array(0, 10, 0, 789742, 2580955), + 'AIRDROP' => array(0, 10, 0, 789742, 2581842), + 'BATCH' => array(0, 10, 0, 789742, 2581531), 'BET' => array(0, 10, 0, 9999999, 999999999), 'CALLBACK' => array(0, 10, 0, 9999999, 999999999), 'DESTROY' => array(0, 10, 0, 789742, 2473585), From 7db8b84aeb7681eb3eae8544e045a2be323d0f07 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Mon, 18 Mar 2024 13:27:44 -0700 Subject: [PATCH 37/42] fix airdrop format 1 parsing --- indexer/includes/actions/airdrop.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/indexer/includes/actions/airdrop.php b/indexer/includes/actions/airdrop.php index 0a9458a..0de28c2 100644 --- a/indexer/includes/actions/airdrop.php +++ b/indexer/includes/actions/airdrop.php @@ -11,7 +11,7 @@ * * FORMATS: * - 0 = Single Airdrop - * - 1 = Multi-Airdrop (brief) + * - 1 = Multi-Airdrop (Brief) * - 2 = Multi-Airdrop (Full) * - 3 = Multi-Airdrop (Full) with Multiple Memos * @@ -30,9 +30,16 @@ function btnsAirdrop($params=null, $data=null, $error=null){ /***************************************************************** * DEBUGGING - Force params ****************************************************************/ - // $str = '0|AIRDROPTEST1|1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|test'; // ADDRESS LIST - // $str = '0|AIRDROPTEST2|1|55cd98493c0fe46aed95225d909a82793a9ba7b480dccdb3170a9cd1ce081093|test'; // TICK LIST - // $str = '0|AIRDROPTEST3|1|afd33c2042cd43b229a44c406f03bcc940702f9736f5a222dfa53295b641a00d|test'; // ASSET LIST + // Single Airdrop + // $str = '0|AIRDROPTEST1|1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|test'; // ADDRESS LIST + // $str = '0|AIRDROPTEST2|1|55cd98493c0fe46aed95225d909a82793a9ba7b480dccdb3170a9cd1ce081093|test'; // TICK LIST + // $str = '0|AIRDROPTEST3|1|afd33c2042cd43b229a44c406f03bcc940702f9736f5a222dfa53295b641a00d|test'; // ASSET LIST + // Multi-Airdrop (brief) + // $str = '1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|AIRDROPTEST1|1|AIRDROPTEST2|2|test brief'; + // Multi-Airdrop (Full) + // $str = '2|AIRDROPTEST1|1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|AIRDROPTEST2|2|55cd98493c0fe46aed95225d909a82793a9ba7b480dccdb3170a9cd1ce081093|test full'; + // Multi-Airdrop (Full) w multiple memos + // $str = '3|AIRDROPTEST1|1|fbe2a4946dfefb232571d56ed1c84dd85299736ba356dc300296d65d59991362|memo1|AIRDROPTEST2|2|55cd98493c0fe46aed95225d909a82793a9ba7b480dccdb3170a9cd1ce081093|memo2|AIRDROPTEST3|3|afd33c2042cd43b229a44c406f03bcc940702f9736f5a222dfa53295b641a00d|memo3'; // $params = explode('|',$str); // Validate that broadcast format is known @@ -60,7 +67,7 @@ function btnsAirdrop($params=null, $data=null, $error=null){ // Multi-Airdrop (brief) if($format==1 && $idx>1 && $idx%2==1) - array_push($airdrops,[$params[1], $params[$idx-1], $params[$idx], $memo]); + array_push($airdrops,[$params[$idx-1], $params[$idx], $params[1], $memo]); // Multi-Airdrop (Full) if($format==2 && $idx>0 && $idx%3==1 && $idx < $lastIdx) From 184e4af395bb8b5f686df58f6b3dc10cf5edae74 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 20 Mar 2024 10:33:44 -0700 Subject: [PATCH 38/42] add address validation to `getAssetHolders()` --- indexer/includes/functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 4358244..37c6e06 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -1711,7 +1711,8 @@ function getAssetHolders( $asset=null, $block_index=null ){ if($results->num_rows){ while($row = $results->fetch_assoc()){ $row = (object) $row; - $holders[$row->address] = $row->credits; + if(isCryptoAddress($row->address)) + $holders[$row->address] = $row->credits; } } } else { From 1f8d1f3f0c053c741d47427c29ab7aa93e66f612 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Wed, 20 Mar 2024 11:14:37 -0700 Subject: [PATCH 39/42] cleanup --- indexer/includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 37c6e06..1929b0b 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -2278,7 +2278,7 @@ function createAirdrop( $data=null ){ $tick_id = createTicker($data->TICK); $source_id = createAddress($data->SOURCE); $tx_hash_id = createTransaction($data->TX_HASH); - $list_id = createMemo($data->LIST); + $list_id = createTransaction($data->LIST); $memo_id = createMemo($data->MEMO); $status_id = createStatus($data->STATUS); $tx_index = $mysqli->real_escape_string($data->TX_INDEX); From 00bacabe79b4f7dc3cc7104f7660bfbeea614198 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Thu, 21 Mar 2024 11:49:01 -0700 Subject: [PATCH 40/42] rollback cleanup - Pull address/ticker data from various tables --- indexer/includes/rollback.php | 104 ++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 23 deletions(-) diff --git a/indexer/includes/rollback.php b/indexer/includes/rollback.php index 009f04e..5245e3f 100644 --- a/indexer/includes/rollback.php +++ b/indexer/includes/rollback.php @@ -3,7 +3,7 @@ * rollback.php - Handles rolling back database updates safely ********************************************************************/ function btnsRollback($block_index=null){ - global $mysqli; + global $mysqli, $addresses, $tickers; $block_index = (int) $block_index; @@ -24,9 +24,7 @@ function btnsRollback($block_index=null){ 'transactions' ]; - // Arrays to track address/tick/transaction ids - $addresses = array(); - $tickers = array(); + // Array to track transaction ids $transactions = array(); $timer = new Profiler(); @@ -36,7 +34,10 @@ function btnsRollback($block_index=null){ // Loop through all database tables foreach($tables as $table){ - // Get list of any addresses or tickers associated with the rollback blocks + // Build out the correct SQL to pull data from the various tables + $sql = false; + + // Credits / Debits if(in_array($table, array('credits','debits'))){ $sql = "SELECT a.address, @@ -49,33 +50,90 @@ function btnsRollback($block_index=null){ t2.id=t1.tick_id AND a.id=t1.address_id AND t1.block_index>{$block_index}"; - $results = $mysqli->query($sql); - if($results){ - if($results->num_rows){ - while($row = $results->fetch_assoc()){ - $row = (object) $row; - if(!in_array($row->address, $addresses)) - array_push($addresses, $row->address); - if(!in_array($row->tick, $tickers)) - array_push($tickers, $row->tick); - } - } - } else { - byeLog("Error while trying to lookup rollback data in the {$table} table"); - } + } + + // AIRDROP / DESTROY + if(in_array($table, array('airdrops','destroys'))){ + $sql = "SELECT + t2.tick, + a.address + FROM + {$table} t1, + index_tickers t2, + index_addresses a + WHERE + t2.id=t1.tick_id AND + a.id=t1.source_id AND + t1.block_index>{$block_index}"; + } + + // MINT / SEND / FEE + if(in_array($table, array('mints','sends','fees'))){ + $sql = "SELECT + t2.tick, + a.address, + a2.address as address2 + FROM + {$table} t1 + LEFT JOIN index_addresses a2 on (t1.destination_id=a2.id), + index_tickers t2, + index_addresses a + WHERE + t2.id=t1.tick_id AND + a.id=t1.source_id AND + t1.block_index>{$block_index}"; + } + + // ISSUE + if($table=='issues'){ + $sql = "SELECT + t2.tick, + a.address, + a2.address as address2, + a3.address as address3 + FROM + {$table} t1 + LEFT JOIN index_addresses a2 on (t1.transfer_id=a2.id) + LEFT JOIN index_addresses a3 on (t1.transfer_supply_id=a3.id), + index_tickers t2, + index_addresses a + WHERE + t2.id=t1.tick_id AND + a.id=t1.source_id AND + t1.block_index>={$block_index}"; } // Get list of transactions associated with the rollback blocks if($table=='transactions'){ - $results = $mysqli->query("SELECT tx_hash_id FROM transactions WHERE block_index>{$block_index}"); + $sql = "SELECT + tx_hash_id + FROM + transactions + WHERE + block_index>{$block_index}"; + } + + // Run the SQL query and populate the addresses, tickers, and transactions arrays + if($sql){ + $results = $mysqli->query($sql); if($results){ if($results->num_rows){ while($row = $results->fetch_assoc()){ $row = (object) $row; - if(!in_array($row->tx_hash_id, $transactions)) - array_push($transactions, $row->tx_hash_id); + if($table=='transactions'){ + if(!in_array($row->tx_hash_id, $transactions)) + array_push($transactions, $row->tx_hash_id); + } else { + addAddressTicker($row->address, $row->tick); + if(!is_null($row->address2)) + addAddressTicker($row->address2, $row->tick); + if(!is_null($row->address3)) + addAddressTicker($row->address3, $row->tick); + } } } + } else { + byeLog("Error while trying to lookup rollback data in the {$table} table"); } } @@ -86,7 +144,7 @@ function btnsRollback($block_index=null){ } // Update address balances to get back to sane balances based on credits/debits - updateBalances($addresses, true); + updateBalances(array_keys($addresses), true); // Update token information updateTokens($tickers, true); From e4b973c59e70c3d5009e7732159962a73e2a2a4c Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 22 Mar 2024 01:56:43 -0700 Subject: [PATCH 41/42] issue updates / cleanup - relaxed sql field definitions for issues table - cleaned up `createIssue()` - updated `getTokenSupply()` to support tick_id - updated `getTokenDecimalPrecision()` to lookup data using issues table - fixed `isDistributed()` to work with `getTokenInfo()` - support legacy BTNS format on ISSUE/MINT/SEND --- indexer/includes/actions/issue.php | 2 +- indexer/includes/functions.php | 136 +++++++++++++++++------------ indexer/sql/issues.sql | 60 +++++++------ 3 files changed, 113 insertions(+), 85 deletions(-) diff --git a/indexer/includes/actions/issue.php b/indexer/includes/actions/issue.php index f731b39..92d01b1 100644 --- a/indexer/includes/actions/issue.php +++ b/indexer/includes/actions/issue.php @@ -172,7 +172,7 @@ function btnsIssue( $params=null, $data=null, $error=null){ $error = 'invalid: MAX_SUPPLY (min/max)'; // Verify MAX_SUPPLY is not set below current SUPPLY - if(!$error && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY > 0 && $data->MAX_SUPPLY < getTokenSupply($data->TICK, $data->BLOCK_INDEX, $data->TX_INDEX)) + if(!$error && isset($data->MAX_SUPPLY) && $data->MAX_SUPPLY > 0 && $data->MAX_SUPPLY < getTokenSupply($data->TICK, null, $data->BLOCK_INDEX, $data->TX_INDEX)) $error = 'invalid: MAX_SUPPLY < SUPPLY'; // Verify SUPPLY is at least MIN_TOKEN_SUPPLY before allowing LOCK_MAX_SUPPLY diff --git a/indexer/includes/functions.php b/indexer/includes/functions.php index 1929b0b..acc4452 100644 --- a/indexer/includes/functions.php +++ b/indexer/includes/functions.php @@ -213,47 +213,46 @@ function createAction( $action=null ){ // Create record in `issues` table function createIssue( $data=null ){ global $mysqli; - // Convert supply amounts to integers - $max_supply = (isset($data->MAX_SUPPLY) && is_numeric($data->MAX_SUPPLY)) ? $data->MAX_SUPPLY : 0; - $max_mint = (isset($data->MAX_MINT) && is_numeric($data->MAX_MINT)) ? $data->MAX_MINT : 0; - $mint_supply = (isset($data->MINT_SUPPLY) && is_numeric($data->MINT_SUPPLY)) ? $data->MINT_SUPPLY : 0; - $mint_address_max = (isset($data->MINT_ADDRESS_MAX) && is_numeric($data->MINT_ADDRESS_MAX)) ? $data->MINT_ADDRESS_MAX : 0; - $mint_start_block = (isset($data->MINT_START_BLOCK) && is_numeric($data->MINT_START_BLOCK)) ? $data->MINT_START_BLOCK : 0; - $mint_stop_block = (isset($data->MINT_STOP_BLOCK) && is_numeric($data->MINT_STOP_BLOCK)) ? $data->MINT_STOP_BLOCK : 0; - $callback_amount = (isset($data->CALLBACK_AMOUNT) && is_numeric($data->CALLBACK_AMOUNT)) ? $data->CALLBACK_AMOUNT : 0; - $decimals = (isset($data->DECIMALS)) ? $data->DECIMALS : 0; - // Truncate description to 250 chars - $description = substr($data->DESCRIPTION,0,250); - // Force any amount values to the correct decimal precision - if(is_numeric($decimals) && $decimals>=0 && $decimals<=18){ - $max_supply = bcmul($max_supply,1,$decimals); - $max_mint = bcmul($max_mint,1,$decimals); - $mint_supply = bcmul($mint_supply,1,$decimals); - $mint_address_max = bcmul($mint_address_max,1,$decimals); - $callback_amount = bcmul($callback_amount,1,$decimals); - } - $max_supply = $mysqli->real_escape_string($max_supply); - $max_mint = $mysqli->real_escape_string($max_mint); - $mint_supply = $mysqli->real_escape_string($mint_supply); - $mint_address_max = $mysqli->real_escape_string($mint_address_max); - $mint_start_block = $mysqli->real_escape_string($mint_start_block); - $mint_stop_block = $mysqli->real_escape_string($mint_stop_block); - $decimals = $mysqli->real_escape_string($decimals); - $description = $mysqli->real_escape_string($description); + // Define list of LOCK fields + $locks = array( + 'LOCK_MAX_SUPPLY', + 'LOCK_MINT', + 'LOCK_MINT_SUPPLY', + 'LOCK_MAX_MINT', + 'LOCK_DESCRIPTION', + 'LOCK_RUG', + 'LOCK_SLEEP', + 'LOCK_CALLBACK' + ); + // Unset any LOCK fields with invalid values + foreach($locks as $lock) + if(!in_array($data->{$lock},array(0,1))) + unset($data->{$lock}); + // Unset DECIMALS if it is outside of the acceptable range + if(isset($data->DECIMALS) && ($data->DECIMALS < MIN_TOKEN_DECIMALS || $data->DECIMALS > MAX_TOKEN_DECIMALS)) + unset($data->DECIMALS); + // Make data safe for use in SQL queries + $description = $mysqli->real_escape_string(substr($data->DESCRIPTION,0,250)); // Truncate description to 250 chars + $max_supply = $mysqli->real_escape_string($data->MAX_SUPPLY); + $max_mint = $mysqli->real_escape_string($data->MAX_MINT); + $mint_supply = $mysqli->real_escape_string($data->MINT_SUPPLY); + $mint_address_max = $mysqli->real_escape_string($data->MINT_ADDRESS_MAX); + $mint_start_block = $mysqli->real_escape_string($data->MINT_START_BLOCK); + $mint_stop_block = $mysqli->real_escape_string($data->MINT_STOP_BLOCK); + $decimals = $mysqli->real_escape_string($data->DECIMALS); $block_index = $mysqli->real_escape_string($data->BLOCK_INDEX); $tx_index = $mysqli->real_escape_string($data->TX_INDEX); $status = $mysqli->real_escape_string($data->STATUS); - // Force lock fields to integer values - $lock_max_supply = ($data->LOCK_MAX_SUPPLY==1) ? 1 : 0; - $lock_mint = ($data->LOCK_MINT==1) ? 1 : 0; - $lock_mint_supply = ($data->LOCK_MINT_SUPPLY==1) ? 1 : 0; - $lock_max_mint = ($data->LOCK_MAX_MINT==1) ? 1 : 0; - $lock_description = ($data->LOCK_DESCRIPTION==1) ? 1 : 0; - $lock_rug = ($data->LOCK_RUG==1) ? 1 : 0; - $lock_sleep = ($data->LOCK_SLEEP==1) ? 1 : 0; - $lock_callback = ($data->LOCK_CALLBACK==1) ? 1 : 0; - $callback_block = ($data->CALLBACK_BLOCK>0) ? $data->CALLBACK_BLOCK : 0; - $callback_amount = $mysqli->real_escape_string($callback_amount); + $lock_max_supply = $mysqli->real_escape_string($data->LOCK_MAX_SUPPLY); + $lock_mint = $mysqli->real_escape_string($data->LOCK_MINT); + $lock_mint_supply = $mysqli->real_escape_string($data->LOCK_MINT_SUPPLY); + $lock_max_mint = $mysqli->real_escape_string($data->LOCK_MAX_MINT); + $lock_description = $mysqli->real_escape_string($data->LOCK_DESCRIPTION); + $lock_rug = $mysqli->real_escape_string($data->LOCK_RUG); + $lock_sleep = $mysqli->real_escape_string($data->LOCK_SLEEP); + $lock_callback = $mysqli->real_escape_string($data->LOCK_CALLBACK); + $callback_block = $mysqli->real_escape_string($data->CALLBACK_BLOCK); + $callback_amount = $mysqli->real_escape_string($data->CALLBACK_AMOUNT); $callback_tick_id = createTicker($data->CALLBACK_TICK); $tick_id = createTicker($data->TICK); $source_id = createAddress($data->SOURCE); @@ -471,7 +470,7 @@ function createToken( $data=null ){ $mint_start_block = (isset($data->MINT_START_BLOCK) && is_numeric($data->MINT_START_BLOCK)) ? $data->MINT_START_BLOCK : 0; $mint_stop_block = (isset($data->MINT_STOP_BLOCK) && is_numeric($data->MINT_STOP_BLOCK)) ? $data->MINT_STOP_BLOCK : 0; $callback_amount = (isset($data->CALLBACK_AMOUNT) && is_numeric($data->CALLBACK_AMOUNT)) ? $data->CALLBACK_AMOUNT : 0; - $decimals = (isset($data->DECIMALS)) ? $data->DECIMALS : 0; + $decimals = (isset($data->DECIMALS) && is_numeric($data->DECIMALS)) ? intval($data->DECIMALS) : 0; // Force any amount values to the correct decimal precision if(is_numeric($decimals) && $decimals>=0 && $decimals<=18){ $max_supply = bcmul($max_supply,1,$decimals); @@ -864,8 +863,9 @@ function deleteLists($list=null, $rollback=null){ // Handle getting token information using issues table function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=null){ global $mysqli; - $data = false; + $data = false; $whereSql = ""; + // Get the tick_id for the given ticker if(!is_null($tick) && is_null($tick_id)) $tick_id = createTicker($tick); // If a block index was given, only lookup tokens created before or in given block @@ -927,7 +927,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu 'OWNER' => ($row->transfer) ? $row->transfer : $row->owner, 'MAX_SUPPLY' => $row->max_supply, 'MAX_MINT' => $row->max_mint, - 'DECIMALS' => $row->decimals, + 'DECIMALS' => (isset($row->decimals)) ? intval($row->decimals) : 0, 'DESCRIPTION' => $row->description, 'OWNER' => $row->owner, 'LOCK_MAX_SUPPLY' => $row->lock_max_supply, @@ -954,6 +954,9 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu if(substr($key,0,5)=='LOCK_') if($data[$key]==1) continue; + // Skip setting value if value is null + if(in_array($key,array('MAX_SUPPLY','MAX_MINT')) && !isset($value)) + continue; $data[$key] = $value; } } @@ -963,7 +966,7 @@ function getTokenInfo($tick=null, $tick_id=null, $block_index=null, $tx_index=nu } if($data){ // Get token supply at the given tx_index - $data['SUPPLY'] = getTokenSupply($tick, null, $tx_index); + $data['SUPPLY'] = getTokenSupply($tick, $tick_id, null, $tx_index); $data = (object) $data; } return $data; @@ -1054,8 +1057,33 @@ function getAssetInfo($asset=null, $block_index=null){ // Handle getting decimal precision for a given tick_id function getTokenDecimalPrecision($tick_id=null){ - $info = getTokenInfo(null, $tick_id); - $decimals = ($info) ? $info->DECIMALS : 0; + global $mysqli; + // print "getTokenDecimalPrecision tick_id={$tick_id}\n"; + // Lookup decimal precision using the issues table + // DO NOT lookup precision using getTokenInfo() (avoid recursive queries) + $decimals = 0; + $sql = "SELECT + i.decimals + FROM + issues i, + index_statuses s + WHERE + i.status_id=s.id AND + i.tick_id='{$tick_id}' AND + s.status='valid'"; + // print $sql; + $results = $mysqli->query($sql); + if($results){ + if($results->num_rows){ + while($row = $results->fetch_assoc()){ + $row = (object) $row; + if(isset($row->decimals) && $row->decimals > $decimals) + $decimals = $row->decimals; + } + } + } else { + byeLog("Error while trying to lookup decimal precision from the issues table for tick: {$tick_id}"); + } return $decimals; } @@ -1297,13 +1325,15 @@ function updateTokenInfo( $tick=null ){ // @param {tick} string Ticker name // @param {block_index} integer Block Index // @param {tx_index} integer tx_index of transaction -function getTokenSupply( $tick=null, $block_index=null, $tx_index=null ){ +function getTokenSupply( $tick=null, $tick_id=null, $block_index=null, $tx_index=null ){ global $mysqli; $credits = 0; $debits = 0; $supply = 0; $block = (is_numeric($block_index)) ? $block_index : 99999999999999; - $tick_id = createTicker($tick); + // Get the tick_id for the given ticker + if(!is_null($tick) && is_null($tick_id)) + $tick_id = createTicker($tick); // Get info on decimal precision $decimals = getTokenDecimalPrecision($tick_id); $whereSql = ""; @@ -1751,7 +1781,7 @@ function getAssetHolders( $asset=null, $block_index=null ){ // Determine if an ticker is distributed to users (held by more than owner) function isDistributed($tick=null, $block_index=null, $tx_index=null){ - $info = getTokenInfo($tick, $block_index, $tx_index); + $info = getTokenInfo($tick, null, $block_index, $tx_index); $holders = ($info) ? getHolders($tick, $block_index, $tx_index) : []; // More than one holder if(count($holders)>1) @@ -2040,10 +2070,6 @@ function processTransaction($tx=null){ // Extract ACTION from PARAMS $action = strtoupper(array_shift($params)); - // Support legacy BTNS format with no VERSION on DEPLOY/MINT/TRANSFER actions (default to VERSION 0) - if(in_array($action,array('DEPLOY','MINT','TRANSFER')) && isLegacyBTNSFormat($params)) - array_splice($params, 0, 0, 0); - // Define ACTION aliases $aliases = array( // Old BRC20/SRC20 actions @@ -2058,6 +2084,10 @@ function processTransaction($tx=null){ if($action==$alias) $action = $act; + // Support legacy BTNS format with no VERSION (default to VERSION 0) + if(in_array($action,array('ISSUE','MINT','SEND')) && isLegacyBTNSFormat($params)) + array_splice($params, 0, 0, 0); + // Define basic BTNS transaction data object $data = (object) array( 'ACTION' => $action, // Action (ISSUE, MINT, SEND, etc) @@ -2416,8 +2446,4 @@ function createFeeRecord( $data=null ){ } } - - - - ?> diff --git a/indexer/sql/issues.sql b/indexer/sql/issues.sql index 86053b5..bda14fa 100644 --- a/indexer/sql/issues.sql +++ b/indexer/sql/issues.sql @@ -1,34 +1,34 @@ DROP TABLE IF EXISTS issues; CREATE TABLE issues ( - tx_index INTEGER UNSIGNED NOT NULL, -- Unique transaction index - tick_id INTEGER UNSIGNED, -- id of record in index_tickers table - max_supply VARCHAR(250), -- Maximum token supply (1000000000000000000000.000000000000000000 = 40 Characters) - max_mint VARCHAR(250), -- Maximum amount of supply a MINT transaction can issue - decimals INTEGER(2) UNSIGNED, -- Number of decimal places token should have (max: 18, default: 0) - description VARCHAR(250), -- URL to a an icon to use for this token (48x48 standard size) - mint_supply VARCHAR(250), -- Maximum amount of supply a MINT transaction can issue - transfer_id INTEGER UNSIGNED, -- id of record in index_addresses table - transfer_supply_id INTEGER UNSIGNED, -- id of record in index_addresses table - lock_max_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_SUPPLY - lock_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT - lock_mint_supply TINYINT(1) NOT NULL DEFAULT 0, -- Locks MINT_SUPPLY - lock_max_mint TINYINT(1) NOT NULL DEFAULT 0, -- Locks MAX_MINT - lock_description TINYINT(1) NOT NULL DEFAULT 0, -- Locks DESCRIPTION - lock_rug TINYINT(1) NOT NULL DEFAULT 0, -- Locks RUG - lock_sleep TINYINT(1) NOT NULL DEFAULT 0, -- Locks SLEEP - lock_callback TINYINT(1) NOT NULL DEFAULT 0, -- Locks CALLBACK_BLOCK/TICK/AMOUNT - callback_block INTEGER UNSIGNED, -- block_index after which CALLBACK cand be used - callback_tick_id INTEGER UNSIGNED, -- id of record in index_tickers table - callback_amount VARCHAR(250), -- AMOUNT users get if CALLBACK - allow_list_id INTEGER UNSIGNED NOT NULL default 0, -- id of record in index_transactions table - block_list_id INTEGER UNSIGNED NOT NULL default 0, -- id of record in index_transactions table - mint_address_max VARCHAR(250), -- Maximum amount of supply an address can MINT - mint_start_block INTEGER UNSIGNED, -- block_index when MINT transactions are allowed (begin mint) - mint_stop_block INTEGER UNSIGNED, -- BLOCK_INDEX when MINT transactions are NOT allowed (end mint) - source_id INTEGER UNSIGNED, -- id of record in index_addresses table (address that did DEPLOY) - tx_hash_id INTEGER UNSIGNED, -- id of record in index_transactions - block_index INTEGER UNSIGNED, -- block index of DEPLOY transaction - status_id INTEGER UNSIGNED -- id of record in index_statuses table + tx_index INTEGER UNSIGNED NOT NULL, -- Unique transaction index + tick_id INTEGER UNSIGNED, -- id of record in index_tickers table + max_supply VARCHAR(250), -- Maximum token supply (1000000000000000000000.000000000000000000 = 40 Characters) + max_mint VARCHAR(250), -- Maximum amount of supply a MINT transaction can issue + decimals VARCHAR(2), -- Number of decimal places token should have (max: 18, default: 0) + description VARCHAR(250), -- URL to a an icon to use for this token (48x48 standard size) + mint_supply VARCHAR(250), -- Maximum amount of supply a MINT transaction can issue + transfer_id INTEGER UNSIGNED, -- id of record in index_addresses table + transfer_supply_id INTEGER UNSIGNED, -- id of record in index_addresses table + lock_max_supply VARCHAR(1), -- Locks MAX_SUPPLY + lock_mint VARCHAR(1), -- Locks MINT + lock_mint_supply VARCHAR(1), -- Locks MINT_SUPPLY + lock_max_mint VARCHAR(1), -- Locks MAX_MINT + lock_description VARCHAR(1), -- Locks DESCRIPTION + lock_rug VARCHAR(1), -- Locks RUG + lock_sleep VARCHAR(1), -- Locks SLEEP + lock_callback VARCHAR(1), -- Locks CALLBACK_BLOCK/TICK/AMOUNT + callback_block VARCHAR(15), -- block_index after which CALLBACK cand be used + callback_tick_id INTEGER UNSIGNED, -- id of record in index_tickers table + callback_amount VARCHAR(250), -- AMOUNT users get if CALLBACK + allow_list_id INTEGER UNSIGNED, -- id of record in index_transactions table + block_list_id INTEGER UNSIGNED, -- id of record in index_transactions table + mint_address_max VARCHAR(250), -- Maximum amount of supply an address can MINT + mint_start_block VARCHAR(15), -- block_index when MINT transactions are allowed (begin mint) + mint_stop_block VARCHAR(15), -- BLOCK_INDEX when MINT transactions are NOT allowed (end mint) + source_id INTEGER UNSIGNED, -- id of record in index_addresses table (address that did DEPLOY) + tx_hash_id INTEGER UNSIGNED, -- id of record in index_transactions + block_index INTEGER UNSIGNED, -- block index of DEPLOY transaction + status_id INTEGER UNSIGNED -- id of record in index_statuses table ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE UNIQUE INDEX tx_index ON issues (tx_index); @@ -42,3 +42,5 @@ CREATE INDEX tx_hash_id ON issues (tx_hash_id); CREATE INDEX callback_tick_id ON issues (callback_tick_id); CREATE INDEX allow_list_id ON issues (allow_list_id); CREATE INDEX block_list_id ON issues (block_list_id); + + From 357b35091bfefed863c5f9f5d53f25463717e459 Mon Sep 17 00:00:00 2001 From: J-Dog Date: Fri, 22 Mar 2024 09:08:18 -0700 Subject: [PATCH 42/42] version bump to 0.12.0 --- indexer/CHANGELOG.md | 11 +++++++++++ indexer/includes/config.php | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/indexer/CHANGELOG.md b/indexer/CHANGELOG.md index 62e2467..b1cc352 100644 --- a/indexer/CHANGELOG.md +++ b/indexer/CHANGELOG.md @@ -1,5 +1,16 @@ CHANGELOG --- +0.12.0 +- Added support for `--reparse` +- Optimized ledger hashing +- `ADDRESS` support +- Renamed `LOCK_MINT` param to `LOCK_MAX_MINT` +- Renamed `LOCK_SUPPLY` param to `LOCK_MAX_SUPPLY` +- Added `LOCK_MINT` param to lock against `MINT` command +- Added `LOCK_MINT_SUPPLY` param +- `BATCH` support +- `AIRDROP` support + 0.11.1 - Added support for `MINT_START_BLOCK` - Added support for `MINT_STOP_BLOCK` diff --git a/indexer/includes/config.php b/indexer/includes/config.php index 4bf305d..104393e 100644 --- a/indexer/includes/config.php +++ b/indexer/includes/config.php @@ -9,8 +9,8 @@ // BTNS Indexer Version define("VERSION_MAJOR", 0); -define("VERSION_MINOR", 11); -define("VERSION_REVISION",1); +define("VERSION_MINOR", 12); +define("VERSION_REVISION",0); define("VERSION_STRING", VERSION_MAJOR . '.' . VERSION_MINOR . '.' . VERSION_REVISION); // TICK constants