Decentralized Devtax #305

Merged
duke merged 13 commits from danger into duke 6 months ago
duke commented 11 months ago
Owner

This code still needs some changes and testing before being merged :

  • Set a production fork block height
  • Update code with production scriptpubs
  • Test on a testcoin called TUSH3 that verifies new scriptpubs are cycled thru

Code below should be considered pseudo-code, the real code is in the git commits.

Technical background

Currently HUSH mainnet use the -ac_script param to set the pubkey of the devtax taddr. Instead of via the CLI param, it's set in C++ code in src/hush_utils.h :

 // this corresponds to FR address RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn
ASSETCHAINS_SCRIPTPUB  = "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac";

Currently the internals assume that this value is set once at run-time (actually compile-time for HUSH3 since it's hardcoded in C++) and never changes. A decentralized devtax (DeDevtax) means there will be a pool of 20 addresses, known at compile time, which are cycled thru. This may require some internals code changes to allow for this. At a high level, there are 2 main places in the code that need to change :

  • Code related to mining in src/miner.cpp (only solo miners + pools run this)
  • Code related to checking consensus in src/hush_bitcoind.h (all nodes run this)

The internals should actually keep the above value hardcoded so that network magic (which is used to derive rpc/p2p ports/etc) does not change. When a new block template is created for a miner to propose a new block, that is when a taddr/pubkey from the pool should be chosen.

The CreateNewBlock and CreateNewBlockWithKey functions in src/miner.cpp need to change to choose from the pool of new pubkeys. It is actually pubkeys of taddrs, not taddrs directly, that are stored in the code. Both functions have this code which needs to change :

                int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str());
                len >>= 1;
                txNew.vout[1].scriptPubKey.resize(len);
                ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0];
                decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str());

There should be a new function which returns a scriptpub based on the current block height trying to be mined (which is +1 from the current chain tip) :

// this is a deterministic consensus-changing function. All miners must be able
// to predict the scriptpub for the next block
std::string scriptpub_for_height(int height) {
    bool ishush3  = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false;
    bool istush3  = strncmp(SMART_CHAIN_SYMBOL, "TUSH3",5) == 0 ? true : false;
    // Fork height for HUSH3 mainnet needs to be decided just before code is merged
    // Since it requires all full nodes on the network to have enough time to update.
    // For testing, we choose an early blockheight so we can observe the value changing
    // from the old fixed value to the new values which cycle
    const int DEVTAX_FORK_HEIGHT = ishush3 ? XXX : 5;
    std::string devtax_scriptpubs = { /* array of 20 scriptpubs */ };
    
    // this change must be height-activated
    if (height >= DEVTAX_FORK_HEIGHT) {
        if (ishush3 || tush3) {
            // devtax_scriptpubs is an array of length 20 with 20 different scriptpubs
            return devtax_scriptpubs[ height % 20 ];
        } else {
    	    // if this is not HUSH3 or a testchain for HUSH3, return it unchanged
    	    return ASSETCHAINS_SCRIPTPUB;
        }
    } else {
    	// return default unchanged if we are less than fork height
        return ASSETCHAINS_SCRIPTPUB;
    }
}

So the new code would be something like :

                ASSETCHINS_SCRIPTPUB = scriptpub_for_height(Mining_height);
                int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str());
                len >>= 1;
                txNew.vout[1].scriptPubKey.resize(len);
                ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0];
                decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str());


The function hush_checkcommission() in src/hush_bitcoind.h needs to change, to know about the cycling of ASSETCHAINS_SCRIPTPUB instead of it being fixed. This function is called by hush_checkPOW() which is used by src/main.cpp. Note that HUSH mainnet nor any existing HSC does not use HUSH_EARLYTXID, so code related to that does not execute.

This code :

               if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) )
                {
                    decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str());
                    if ( memcmp(scripthex,script,scriptlen) == 0 )
                        matched = scriptlen;
                }

is used during consensus checks on every full node (not just mining nodes) to verify that the ASSETCHAINS_SCRIPTPUB is what it should be. It needs to change to something like :

               ASSETCHINS_SCRIPTPUB = scriptpub_for_height(current_height);
               if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) )
                {
                    decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str());
                    if ( memcmp(scripthex,script,scriptlen) == 0 )
                        matched = scriptlen;
                }

where current_height is the height of the current chaintip. Note that scriptpub_for_height() might be best called at the beginning of the hush_checkcommission function so that all other code there has the correct value for ASSETCHAINS_SCRIPTPUB.

This code still needs some changes and testing before being merged : * [x] Set a production fork block height * [x] Update code with production scriptpubs * [x] Test on a testcoin called TUSH3 that verifies new scriptpubs are cycled thru Code below should be considered pseudo-code, the real code is in the git commits. # Technical background Currently HUSH mainnet use the `-ac_script` param to set the pubkey of the devtax taddr. Instead of via the CLI param, it's set in C++ code in src/hush_utils.h : ``` // this corresponds to FR address RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn ASSETCHAINS_SCRIPTPUB = "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac"; ``` Currently the internals assume that this value is set once at run-time (actually compile-time for HUSH3 since it's hardcoded in C++) and never changes. A decentralized devtax (DeDevtax) means there will be a pool of 20 addresses, known at compile time, which are cycled thru. This may require some internals code changes to allow for this. At a high level, there are 2 main places in the code that need to change : * Code related to mining in src/miner.cpp (only solo miners + pools run this) * Code related to checking consensus in src/hush_bitcoind.h (all nodes run this) The internals should actually keep the above value hardcoded so that network magic (which is used to derive rpc/p2p ports/etc) does not change. When a new block template is created for a miner to propose a new block, that is when a taddr/pubkey from the pool should be chosen. The `CreateNewBlock` and `CreateNewBlockWithKey` functions in src/miner.cpp need to change to choose from the pool of new pubkeys. It is actually pubkeys of taddrs, not taddrs directly, that are stored in the code. Both functions have this code which needs to change : ``` int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str()); len >>= 1; txNew.vout[1].scriptPubKey.resize(len); ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0]; decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); ``` There should be a new function which returns a scriptpub based on the current block height trying to be mined (which is +1 from the current chain tip) : ``` // this is a deterministic consensus-changing function. All miners must be able // to predict the scriptpub for the next block std::string scriptpub_for_height(int height) { bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false; bool istush3 = strncmp(SMART_CHAIN_SYMBOL, "TUSH3",5) == 0 ? true : false; // Fork height for HUSH3 mainnet needs to be decided just before code is merged // Since it requires all full nodes on the network to have enough time to update. // For testing, we choose an early blockheight so we can observe the value changing // from the old fixed value to the new values which cycle const int DEVTAX_FORK_HEIGHT = ishush3 ? XXX : 5; std::string devtax_scriptpubs = { /* array of 20 scriptpubs */ }; // this change must be height-activated if (height >= DEVTAX_FORK_HEIGHT) { if (ishush3 || tush3) { // devtax_scriptpubs is an array of length 20 with 20 different scriptpubs return devtax_scriptpubs[ height % 20 ]; } else { // if this is not HUSH3 or a testchain for HUSH3, return it unchanged return ASSETCHAINS_SCRIPTPUB; } } else { // return default unchanged if we are less than fork height return ASSETCHAINS_SCRIPTPUB; } } ``` So the new code would be something like : ``` ASSETCHINS_SCRIPTPUB = scriptpub_for_height(Mining_height); int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str()); len >>= 1; txNew.vout[1].scriptPubKey.resize(len); ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0]; decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); ```` The function `hush_checkcommission()` in src/hush_bitcoind.h needs to change, to know about the cycling of ASSETCHAINS_SCRIPTPUB instead of it being fixed. This function is called by `hush_checkPOW()` which is used by src/main.cpp. Note that HUSH mainnet nor any existing HSC does not use HUSH_EARLYTXID, so code related to that does not execute. This code : ``` if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) ) { decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); if ( memcmp(scripthex,script,scriptlen) == 0 ) matched = scriptlen; } ``` is used during consensus checks on every full node (not just mining nodes) to verify that the ASSETCHAINS_SCRIPTPUB is what it should be. It needs to change to something like : ``` ASSETCHINS_SCRIPTPUB = scriptpub_for_height(current_height); if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) ) { decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); if ( memcmp(scripthex,script,scriptlen) == 0 ) matched = scriptlen; } ``` where `current_height` is the height of the current chaintip. Note that `scriptpub_for_height()` might be best called at the beginning of the `hush_checkcommission` function so that all other code there has the correct value for ASSETCHAINS_SCRIPTPUB.
duke added the
feature
high priority
labels 11 months ago
duke self-assigned this 11 months ago
duke added 1 commit 11 months ago
duke added 1 commit 11 months ago
duke added 2 commits 11 months ago
duke added 1 commit 10 months ago
duke added 1 commit 7 months ago
duke added 44 commits 7 months ago
e8dc755f06 Reduce memory usage of CBlockIndex
fab9a7f51d Add libleveldb-dev to build dependencies
cf1274a42a Remove unnecessary consistency checks
duke added this to the 3.10.0 milestone 6 months ago
duke added 11 commits 6 months ago
duke added 3 commits 6 months ago
f442823963 Fix unoptimized libraries in depends
duke added 1 commit 6 months ago
duke added 3 commits 6 months ago
Poster
Owner

Hardfork height, production addresses and scriptpubs have been added

Hardfork height, production addresses and scriptpubs have been added
duke changed title from WIP: Decentralized Devtax to Decentralized Devtax 6 months ago
duke merged commit 6d8f261d7a into duke 6 months ago
The pull request has been merged as 6d8f261d7a.
Sign in to join this conversation.
Loading…
There is no content yet.