Skip to content

Commit

Permalink
initial hard fork - eliminate mining pools - sign loop
Browse files Browse the repository at this point in the history
  • Loading branch information
bitcoin-pow committed Jul 3, 2024
1 parent 6ee27e7 commit 0480b1f
Show file tree
Hide file tree
Showing 12 changed files with 296 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
"program": "/home/ubuntu/dev/BitcoinPoW/src/qt/bitcoin-qt",
"args": ["--emergencymining=1","--rescan=0", "--miningthreads=18", "--cpuloading=80"],
//"args": ["--listen=0", "--server=0"],
// ./bitcoin-qt --emergencymining=1 --rescan=0 --miningthreads=18 -cpuloading=80 -datadir=/home/ubuntu/.bitcoin-pow &
// ./bitcoin-qt -listen=0 -forcednsseed=0 -datadir=/home/ubuntu/.btcw2/ -connect=127.0.0.1 &
// ./bitcoind --emergencymining=1 --miningthreads=12 --cpuloading=80 --datadir=/home/ubuntu/.bitcoin-pow
// ./bitcoin-cli --rpccookiefile=/home/ubuntu/.bitcoin-pow/.cookie generate
// ./bitcoin-cli --rpccookiefile=/home/ubuntu/.bitcoin-pow/.cookie getmininginfo
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
AC_PREREQ([2.69])
define(_CLIENT_VERSION_MAJOR, 26)
define(_CLIENT_VERSION_MINOR, 3)
define(_CLIENT_VERSION_MINOR, 4)
define(_CLIENT_VERSION_REVISION, 1)
define(_CLIENT_VERSION_BUILD, 1)
define(_CLIENT_VERSION_RC, 0)
Expand Down
4 changes: 2 additions & 2 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,12 +395,12 @@ class CBlockIndex

bool IsProofOfWork() const
{
return nNonce != 0xFEEDBEEF;
return !IsProofOfStake();
}

bool IsProofOfStake() const
{
return nNonce == 0xFEEDBEEF;
return (nNonce == 0xFEEDBEEF) || (nNonce == 0xFEEDBEE1);
}

std::string ToString() const;
Expand Down
2 changes: 2 additions & 0 deletions src/consensus/consensus.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
static const int64_t MAX_BLOCK_SIGOPS_COST = 80000;
/** The fork start height of SatoshiPoW (network rule) */
static const int64_t BITCOIN_POW256_START_HEIGHT = 23333;
/** The fork start height to eliminate mining pools (network rule) */
static const int64_t BITCOIN_ELIMINATE_MINING_POOLS_START_HEIGHT = 4000000000000; // @TODO, fork height is ???
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
constexpr int COINBASE_MATURITY()
{
Expand Down
11 changes: 6 additions & 5 deletions src/kernel/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // Dec 2023

// The best chain should have at least this much work. - getblockchaininfo
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000004f035d8e9ebf9aef4c");
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000008c3e3681025f7a7cf4f");

// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
Expand Down Expand Up @@ -234,7 +234,8 @@ class CMainParams : public CChainParams {
{ 14180, uint256S("0xef939cd95e947bd72357b754dd75503347b80fbb68a6435b0da7ecdea1da3ae2")},
{ 21111, uint256S("0x7067cd7104e32708f4094cf626c4afcdee8af1a76a5969daa95122b2c0346e5a")},
// BitcoinPoW to More PoW fork
//{ 23333 uint256S("0x????")},
{ 23334, uint256S("0x6ee07434a179056a258e3b0bb12e5f5e4c914f6ea77ed396fbe32962663aded6")},
{ 30550, uint256S("0xa4e1ee471f362b5e00ea20c575755f1dff00d39e2efb13dd6bf861d371436ce1")},
}
};

Expand All @@ -244,9 +245,9 @@ class CMainParams : public CChainParams {

chainTxData = ChainTxData{
// Data from RPC: getchaintxstats
/* nTime */ 1714362313,
/* nTxCount */ 18749063,
/* dTxRate */ 0.2879754883092357,
/* nTime */ 1719970210,
/* nTxCount */ 19447911,
/* dTxRate */ 0.06365420205887741,
};
}
};
Expand Down
31 changes: 20 additions & 11 deletions src/node/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,11 +683,11 @@ void ThreadStakeMiner(wallet::CWallet& wallet, CConnman& connman, ChainstateMana

// Cannot mine with 0 connections.
if (connman.GetNodeCount(ConnectionDirection::Both) == 0 ) {
UninterruptibleSleep(std::chrono::milliseconds{1000});
wallet.m_last_coin_stake_search_interval = 0;
s_hashes_per_second = 0;
s_cpu_loading = 0;
continue;
UninterruptibleSleep(std::chrono::milliseconds{1000});
wallet.m_last_coin_stake_search_interval = 0;
s_hashes_per_second = 0;
s_cpu_loading = 0;
continue;
}

//
Expand Down Expand Up @@ -727,7 +727,7 @@ void ThreadStakeMiner(wallet::CWallet& wallet, CConnman& connman, ChainstateMana
uint32_t newTime=GetAdjustedTime64();

int64_t delta = stop_time - start_time;
s_hashes_per_second = 256 * s_coin_loop_prev_max_idx.load(std::memory_order_relaxed);; // 256 is extra PoW sha256()
s_hashes_per_second = 64 * s_coin_loop_prev_max_idx.load(std::memory_order_relaxed);; // 64 is extra PoW sha256()
s_cpu_loading = delta/10.0 > 100 ? 100.0 : delta/10.0; // This is loading % for a single core that is active.

if ( newTime > beginningTime )
Expand All @@ -752,12 +752,19 @@ void ThreadStakeMiner(wallet::CWallet& wallet, CConnman& connman, ChainstateMana
// nLastCoinStakeSearchInterval > 0 mean that the staker is running
wallet.m_last_coin_stake_search_interval = i - wallet.m_last_coin_stake_search_time;

//
uint32_t nNonce{0xFEEDBEEF};
if ( (chainman.ActiveChain().Tip()->nHeight+1) >= BITCOIN_ELIMINATE_MINING_POOLS_START_HEIGHT )
{
nNonce = 0xFEEDBEE1;// v1 fork nonce
}

// Try to sign a block (this also checks for a PoS stake)
pblocktemplate->block.nTime = i;
pblocktemplate->block.nNonce = 0xFEEDBEEF; // Proof of Transaction Work
pblocktemplate->block.nNonce = nNonce; // Proof of Transaction Work
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);

if (SignBlock(chainman, pblock, wallet, nTotalFees, i, 0xFEEDBEEF, setCoins)) {
LogPrintf("START LOOKING FOR POT============================================\n");
if (SignBlock(chainman, pblock, wallet, nTotalFees, i, nNonce, setCoins, false)) {

if (chainman.ActiveChain().Tip()->GetBlockHash() != pblock->hashPrevBlock) {
//another block was received while building ours, scrap progress
Expand All @@ -767,7 +774,7 @@ void ThreadStakeMiner(wallet::CWallet& wallet, CConnman& connman, ChainstateMana
// Create a block that's properly populated with transactions
std::unique_ptr<CBlockTemplate> pblocktemplatefilled(
BlockAssembler{chainman.ActiveChainstate(), &mempool}.CreateNewBlock(pblock->vtx[1]->vout[1].scriptPubKey, true, &nTotalFees, i));
pblocktemplatefilled->block.nNonce = 0xFEEDBEEF; // Proof of Transaction Work
pblocktemplatefilled->block.nNonce = nNonce; // Proof of Transaction Work
if (!pblocktemplatefilled.get()) {
LogPrintf("ThreadStakeMiner(): Failed to create block template; thread exiting...\n");
goto DONE_MINING;
Expand All @@ -777,9 +784,10 @@ void ThreadStakeMiner(wallet::CWallet& wallet, CConnman& connman, ChainstateMana
LogPrintf("ThreadStakeMiner(): Valid future PoS block was orphaned before becoming valid\n");
break;
}
LogPrintf("FOUND POT SOLUTION - START LOOKING PoW============================================\n");
// Sign the full block and use the timestamp from earlier for a valid stake
std::shared_ptr<CBlock> pblockfilled = std::make_shared<CBlock>(pblocktemplatefilled->block);
if (SignBlock(chainman, pblockfilled, wallet, nTotalFees, i, 0xFEEDBEEF, setCoins)) {
if (SignBlock(chainman, pblockfilled, wallet, nTotalFees, i, nNonce, setCoins, true)) {
// Should always reach here unless we spent too much time processing transactions and the timestamp is now invalid
// CheckStake also does CheckBlock and AcceptBlock to propogate it to the network
bool validBlock = false;
Expand All @@ -804,6 +812,7 @@ void ThreadStakeMiner(wallet::CWallet& wallet, CConnman& connman, ChainstateMana
}
if (validBlock) {
CheckStake(chainman, pblockfilled, wallet);
LogPrintf("FOUND BLOCK============================================\n");
// Update the search time when new valid block is created, needed for status bar icon
wallet.m_last_coin_stake_search_time = pblockfilled->GetBlockTime();
}
Expand Down
67 changes: 65 additions & 2 deletions src/pos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ bool CheckStakeKernelHash(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t
if (nTimeBlock < blockFromTime) // Transaction timestamp violation
return error("CheckStakeKernelHash() : nTime violation");

if (nNonce != 0xFEEDBEEF) // Proof of Transaction Work indicator
if ( !((nNonce == 0xFEEDBEEF) || (nNonce == 0xFEEDBEE1)) ) // Proof of Transaction Work indicator
return error("CheckStakeKernelHash() : nNonce violation");

// Base target with 0 PoS contribution
Expand All @@ -81,6 +81,20 @@ bool CheckStakeKernelHash(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t
// Now check if hash meets target protocol
arith_uint256 actual = UintToArith256(hashProofOfStake);

int loop_cnt = 64;
if ( ((pindexPrev->nHeight + 1) < BITCOIN_ELIMINATE_MINING_POOLS_START_HEIGHT) && ( nNonce == 0xFEEDBEEF ) ) // Hard fork v0
{
loop_cnt = 256;
}
else
{
// Hardfork to eliminate mining pools
bnTarget.SetCompact(nBits);
targetProofOfStake = ArithToUint256(bnTarget);
bnTarget = POW_POT_DIFF_HELPER*bnTarget;
bnTarget *= 100;
}

if ( (pindexPrev->nHeight + 1) < BITCOIN_POW256_START_HEIGHT )
{
if (actual <= bnTarget)
Expand All @@ -101,7 +115,7 @@ bool CheckStakeKernelHash(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t
uint16_t f = 0;
uint16_t g = 0;
auto& chain_active = gp_chainman->m_active_chainstate->m_chain;
for ( volatile int k=1; k<=256; k++ )
for ( volatile int k=1; k<=loop_cnt; k++ )
{
// Grab values from random previous headers
data = actual.GetLow64();
Expand Down Expand Up @@ -260,6 +274,55 @@ bool CheckRecoveredPubKeyFromBlockSignature(CBlockIndex* pindexPrev, const CBloc
}
}

// The fork to eliminate mining pools appends 8 bytes to the signature, remove these 8 bytes and
// see if signature matches.
if( block.vchBlockSig.size() < 8 ) {
return false; // too small and check already failed above
}

// 8 bytes added to signature length tells the nonce number
uint64_t nonce_64[8];
auto vchBlockSig = block.vchBlockSig;

// Signatures are about 68 -> 72 bytes
if( block.vchBlockSig.size() > 60 )
{
for( int n=0; n<8; n++)
{
nonce_64[n] = vchBlockSig.back();
vchBlockSig.pop_back();
}
}
else
{
return false;
}


uint256 hash_no_sig = block.GetHashWithoutSign();
uint64_t nonce = (nonce_64[7]<<56) | (nonce_64[6]<<48) | (nonce_64[5]<<40) | (nonce_64[4]<<32) | (nonce_64[3]<<24) | (nonce_64[2]<<16) | (nonce_64[1]<<8) | (nonce_64[0]);
uint256 mud = ArithToUint256( UintToArith256(hash_no_sig) + arith_uint256(nonce) );

for(uint8_t recid = 0; recid <= 3; ++recid) {
for(uint8_t compressed = 0; compressed < 2; ++compressed) {
if(!pubkey.RecoverLaxDER(mud, vchBlockSig, recid, compressed)) {
continue;
}

CTxDestination address;
TxoutType txType=TxoutType::NONSTANDARD;
if(ExtractDestination(coinPrev.out.scriptPubKey, address, &txType)){
PKHash* pkhash = std::get_if<PKHash>(&address);
if ((txType == TxoutType::PUBKEY || txType == TxoutType::PUBKEYHASH) && pkhash) {
if(PKHash(pubkey.GetID()) == *pkhash) {
return true;
}
}
}
}
}


return false;
}

Expand Down
3 changes: 2 additions & 1 deletion src/pos.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class uint256;
// To decrease granularity of timestamp
// Supposed to be 2^n-1
static const uint32_t STAKE_TIMESTAMP_MASK = 0; // CPU can hash as fast as possible
static const uint32_t POW_POT_DIFF_HELPER = 1000000; // help the transition to PoW/PoT not take a year.
static const uint64_t POW_POT_DIFF_HELPER = 1000000; // help the transition to PoW/PoT not take a year.(Section1 diff)
static const uint64_t SIG_DIFF_ADJ = 100000000; // Adjust the signature diff (Section2 diff)

struct CStakeCache{
CStakeCache(uint32_t blockFromTime_, CAmount amount_) : blockFromTime(blockFromTime_), amount(amount_){
Expand Down
6 changes: 3 additions & 3 deletions src/primitives/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class CBlockHeaderBase

SERIALIZE_METHODS(CBlockHeaderBase, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce);

if (obj.nNonce == 0xFEEDBEEF)
if ( (obj.nNonce == 0xFEEDBEEF) || (obj.nNonce == 0xFEEDBEE1) )
{
READWRITE(obj.prevoutStake);
}
Expand All @@ -56,7 +56,7 @@ class CBlockHeader : public CBlockHeaderBase

SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce);

if (obj.nNonce == 0xFEEDBEEF)
if ( (obj.nNonce == 0xFEEDBEEF) || (obj.nNonce == 0xFEEDBEE1) )
{
READWRITE(obj.prevoutStake);
READWRITE(obj.vchBlockSig);
Expand Down Expand Up @@ -96,7 +96,7 @@ class CBlockHeader : public CBlockHeaderBase
// two types of block: proof-of-work or proof-of-stake
virtual bool IsProofOfStake() const
{
return (this->nNonce == 0xFEEDBEEF);
return ( (nNonce == 0xFEEDBEEF) || (nNonce == 0xFEEDBEE1) );
}

virtual bool IsProofOfWork() const
Expand Down
11 changes: 1 addition & 10 deletions src/util/thread_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_UTIL_THREAD_POOL_H
#define BITCOIN_UTIL_THREAD_POOL_H
#pragma once

#include <functional>
#include <string>
Expand Down Expand Up @@ -78,11 +77,6 @@

namespace util
{
int
hwc() {
return std::thread::hardware_concurrency();
}

/**
* Structure of the class:
*
Expand Down Expand Up @@ -1155,6 +1149,3 @@ namespace util

#endif /* __cplusplus */

//} // namespace util

#endif // BITCOIN_UTIL_THREAD_POOL_H
Loading

4 comments on commit 0480b1f

@StickyFingaz420
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code includes two functions to determine the block type based on the nNonce value.

bool IsProofOfWork() const
{
return nNonce != 0xFEEDBEEF;
return !IsProofOfStake();
}

bool IsProofOfStake() const
{
return nNonce == 0xFEEDBEEF;
return (nNonce == 0xFEEDBEEF) || (nNonce == 0xFEEDBEE1);
}

std::string ToString() const;
Function explanations:

IsProofOfWork():

Checks if nNonce is not equal to 0xFEEDBEEF.
I Think There's a mistake as it returns after the first condition, ignoring the second return !IsProofOfStake();.
IsProofOfStake():

Checks if nNonce equals 0xFEEDBEEF.
Similar mistake as it returns after the first condition, ignoring the second return (nNonce == 0xFEEDBEEF) || (nNonce == 0xFEEDBEE1);.

bool IsProofOfWork() const
{
return nNonce != 0xFEEDBEEF;
}

bool IsProofOfStake() const
{
return (nNonce == 0xFEEDBEEF) || (nNonce == 0xFEEDBEE1);
}
the functions return correct values based on the specified conditions.

@StickyFingaz420
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bool IsProofOfWork() const
{
return nNonce != 0xFEEDBEEF && !IsProofOfStake();
}

bool IsProofOfStake() const
{
return nNonce == 0xFEEDBEEF || nNonce == 0xFEEDBEE1;
}

std::string ToString() const;

@StickyFingaz420
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Cannot mine with 0 connections.
if (connman.GetNodeCount(ConnectionDirection::Both) == 0 ) {
UninterruptibleSleep(std::chrono::milliseconds{1000});
wallet.m_last_coin_stake_search_interval = 0;
s_hashes_per_second = 64 * s_coin_loop_prev_max_idx.load(std::memory_order_relaxed); // Adjusted calculation
s_cpu_loading = 0;
continue; // Skip to next iteration
}

// Other parts of the function...
void ThreadStakeMiner(wallet::CWallet& wallet, CConnman& connman, ChainstateManager& chainman, ...) {
// Previous code here...

uint32_t nNonce = 0xFEEDBEEF;
if ((chainman.ActiveChain().Tip()->nHeight + 1) >= BITCOIN_ELIMINATE_MINING_POOLS_START_HEIGHT) {
    nNonce = 0xFEEDBEE1; // v1 fork nonce
}

// Try to sign a block (this also checks for a PoS stake)
pblocktemplate->block.nTime = i;
pblocktemplate->block.nNonce = nNonce; // Assign nonce once

std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);

if (SignBlock(chainman, pblock, wallet, nTotalFees, i, nNonce, setCoins, false)) {
    LogPrintf("START LOOKING FOR POT============================================\n");

    if (chainman.ActiveChain().Tip()->GetBlockHash() != pblock->hashPrevBlock) {
        // Another block was received while building ours, scrap progress
        // Handle accordingly...
    }

    // Create a block that's properly populated with transactions
    std::unique_ptr<CBlockTemplate> pblocktemplatefilled(
        BlockAssembler{chainman.ActiveChainstate(), &mempool}.CreateNewBlock(pblock->vtx[1]->vout[1].scriptPubKey, true, &nTotalFees, i));

    pblocktemplatefilled->block.nNonce = nNonce; // Assign nonce once

    if (!pblocktemplatefilled) {
        LogPrintf("ThreadStakeMiner(): Failed to create block template; thread exiting...\n");
        goto DONE_MINING;
    }

    LogPrintf("FOUND POT SOLUTION - START LOOKING PoW============================================\n");

    std::shared_ptr<CBlock> pblockfilled = std::make_shared<CBlock>(pblocktemplatefilled->block);

    if (SignBlock(chainman, pblockfilled, wallet, nTotalFees, i, nNonce, setCoins, true)) {
        // Successfully signed the block, proceed with validity checks
        bool validBlock = false;
        // CheckStake also does CheckBlock and AcceptBlock to propagate it to the network
        if (CheckStake(chainman, pblockfilled, wallet)) {
            validBlock = true;
        }

        if (validBlock) {
            LogPrintf("FOUND BLOCK============================================\n");
            // Update the search time when a new valid block is created, needed for status bar icon
            wallet.m_last_coin_stake_search_time = pblockfilled->GetBlockTime();
        }
    }
}
// Other parts of the function...

}

@StickyFingaz420
Copy link
Collaborator

@StickyFingaz420 StickyFingaz420 commented on 0480b1f Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTCW eliminate mining pools, Straight Solo, No Place For Mining Pools Here

Great Job Dev

Please sign in to comment.