Blockcore

repository·master·Indexed 42 days ago

https://github.com/block-core/blockcore

An open-source .NET-based platform written in C# for building Layer 1 consensus networks using the Bitcoin protocol. It serves as an alternative C# Bitcoin implementation focused on open and public blockchains.

Tokens
23.7K
Snippets
45
Records
92
Agent score
53%

What's inside Blockcore

  1. Overview of Blockcore

    master
    Blockcore is an open-source platform for building Layer 1 consensus networks based on the Bitcoin protocol. It is written entirely in C# and built on the .NET Core framework. It serves as an alternative C# Bitcoin implementation, drawing inspiration from the NBitcoin and Stratis projects, with a focus on open and public blockchains.
  2. Write non-entry/exit logs

    master

    Non-entry and non-exit logs provide extra information about the system state or specific events.

    Style Guidelines:

    • Use a unique, concise, English sentence.
    • Do not use [CONTEXT] identifiers (the sentence should provide context).
    • Do not use nameof() or "name:value"/"name=value" notation.
    • Focus on describing the event naturally.
    this.logger.LogTrace("UTXO '{0}/{1}' with value {2} might be available for staking.", stakeTx.OutPoint.Hash, stakeTx.OutPoint.N, utxo.Value);
  3. Understand Cold Staking in Stratis

    master

    Cold staking is a mechanism designed to allow miners to participate in block production without keeping their staking coins in a 'hot wallet' (an online, potentially vulnerable wallet).

    How it works

    Traditionally, a miner must keep coins in a hot wallet to sign coinstake transactions. With cold staking, a special transaction transfers coins to a cold storage wallet (like a hardware or paper wallet) while simultaneously delegating staking rights back to the hot wallet.

    Key Benefits

    • Security: Reduces the risk of theft if a running node or hot wallet is compromised.
    • Participation: Enables safer staking for exchanges and the potential for pool staking.
    • Network Strength: Encourages more users to stake by removing the security barrier of keeping large amounts online.
  4. Understand the PR review policy tags

    master

    Every Pull Request (PR) must be associated with a PR review policy tag. These tags determine the level of scrutiny and the specific requirements for testing and verification required before a change can be merged. The policy levels are:

    • pr-review-critical: Highest level of scrutiny. Requires review by at least two core devs, all tests (Unit and Integration) passing for both author and reviewers, and synchronization of all 4 chains (Bitcoin main/test, Stratis main/test) to an agreed height.
    • pr-review-high: Requires review by at least two core devs, all tests (Unit and Integration) passing for both author and reviewers, and synchronization of all 4 chains (Bitcoin main/test, Stratis main/test) to an agreed height.
    • pr-review-medium: Requires review by at least two core devs (author and reviewer) and all tests (Unit and Integration) passing.
    • pr-review-low: Requires review by at least one core dev and all tests (Unit and Integration) passing.
  5. Understand default logging behavior

    master

    By default, the node uses NLog with a minimum log level of Information for all classes. Logs are sent to both the console and a rotating main log file named node.txt located in the $DATADIR/Logs directory.

    Log Rotation Details:

    • A new log file is created daily.
    • Old logs are renamed using the pattern node-YYYY-MM-DD.N.txt (the timestamp reflects the day the log was rotated, not the day the logs were written).
    • The system archives logs from the last 7 days; files older than 7 days are automatically deleted.
  6. Understand the ProvenHeaders specification

    master

    ProvenHeaders is a security mechanism designed to prevent 'fake header' attacks on Proof-of-Stake (PoS) networks like Stratis. In PoS, attackers can easily construct long chains of fake headers with high perceived chainwork. Without ProvenHeaders, a node might switch to this fake chain and then hang indefinitely while waiting for blocks that will never arrive.

    ProvenHeaders solves this by requiring headers to be accompanied by cryptographic proof of stake (coinstake) to validate the chain's work.

  7. Record execution flow with TRACE logs

    master

    TRACE level logs should be used to record execution flow so that the exact path of object instances can be inspected.

    Best Practices:

    • Distinguishable Branches: Ensure every important execution path branch is distinguishable. You can achieve this by placing a log in one branch, or in both if necessary. If a branch is rarely executed (the 'abnormal' case), logging only in that branch is sufficient to inform the reader that the 'normal' path was taken.
    • Coverage: Logs should provide enough information to reconstruct the state transitions. For example, in a loop, log the state at each iteration rather than just the final exit state to capture the number of operations performed.
    while (true)
    {
        uint256 hash = await this.UTXOSet.Rewind();
        ChainedBlock rewinded = this.Chain.GetBlock(hash);
        if (rewinded == null)
        {
            // Log the specific branch to distinguish it from the successful path
            this.logger.LogTrace("Rewound to '{0}', which is still not a part of the current best chain, rewinding further.", hash);
            continue;
        }
    
        // Log the successful path
        this.logger.LogTrace("Rewound to '{0}'.", hash);
        this.Tip = rewinded;
        this.Puller.SetLocation(rewinded);
        break;
    }
  8. Understand PoA max reorg and signature validation

    master

    In a dynamic PoA federation, headers may be signed by members that a node does not yet recognize, making immediate validation impossible.

    To resolve this, the network uses a max reorg mechanism. Voting results are only executed after max reorg blocks have passed. This ensures the node has sufficient historical data to verify the federation state for the window of CT + 1 to CT + max reorg.

    This logic is implemented in PoAHeaderSignatureRule. Headers located within the max reorg window from the consensus tip that contain invalid signatures are marked as insufficient and are re-validated as the consensus tip advances.

  9. Extending contract transaction validation via DI

    master
    The system uses Dependency Injection (DI) to apply validation rules to contract transactions. The SmartContractPoARuleRegistration automatically injects all registered implementations of IContractTransactionFullValidationRule into the ContractTransactionFullValidationRule. This allows developers to add custom logic to validate the contract transaction format.
  10. Understand the security challenges of Blockcore Proof of Stake

    master

    The Blockcore Proof of Stake (PoS) protocol faces several theoretical and practical security challenges that developers and operators should be aware of:

    Nothing-at-Stake (NAS)

    Validators may have a financial incentive to mine on every fork of the blockchain. This can disrupt consensus and make it difficult for honest nodes to identify the chain with the majority of honest staking power, potentially confusing nodes during Initial Block Download (IBD).

    Stake Grinding

    A validator attempts to bias randomness in their favor by modifying block headers. An attacker with a small amount of stake can scan blockchain history to find opportunities to win blocks and then manipulate subsequent headers to consecutively win blocks.

    The IBD (Initial Block Download) Problem

    During initial sync, a node might be presented with a 'fake chain' (a chain not accepted by the majority of stakers). If the fork is beyond the maxreorg parameter, the local node cannot rewind and may become stuck on the wrong chain.

    Mitigations implemented in Blockcore:

    • Checkpoints: The software includes regularly hard-coded checkpoints of the correct chain to prevent nodes from following fake chains.
    • Connection Restrictions: During IBD, a node will only accept outgoing connections to mitigate the risk of being fed a fake chain by malicious peers.

    General PoS Considerations

    • Complexity: The protocol is more complex than Proof of Work (PoW), which may introduce unknown attack vectors.
    • Decentralization: PoS is often considered less decentralized due to the reliance on checkpoints for IBD and the requirement for a majority of nodes to have synchronized global time.
    • 51% Attack Recovery: In the event of a 51% attack, user intervention (such as utilizing checkpoints) may be required to recover the network.
  11. Use AsyncWrapper for high-volume logging

    master

    To improve performance when logging large volumes of data, use the AsyncWrapper target in your NLog.config.

    Note on Reliability: Async logging may result in lost logs if the program crashes unexpectedly, as logs might not be flushed to disk. For development where crashes are expected, use a standard File target. For testing features where you expect stability, use AsyncWrapper.

    If you handle exceptions manually and want to ensure logs are saved before a crash, call NLog.LogManager.Flush().

    <?xml version="1.0" encoding="utf-8" ?>
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true">
      <targets>
        <target name="debugAllFile" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Block" batchSize="1000">
          <target xsi:type="File" fileName="debug.txt" layout="[${longdate:universalTime=true} ${threadid}${mdlc:item=id}] ${level:uppercase=true}: ${callsite} ${message}" encoding="utf-8" />
        </target>
        <target xsi:type="null" name="null" formatMessage="false" />
      </targets>
    
      <rules>
        <logger name="*" minlevel="Trace" writeTo="null" final="true" />
        <logger name="*" minlevel="Trace" writeTo="debugAllFile" />
      </rules>
    </nlog>
  12. How Smart Contract Whitelisting works

    master

    Smart Contract Whitelisting integrates with the Proof of Authority (PoA) voting feature. The process works as follows:

    1. Hashing: The system hashes the bytecode of any contract creation transaction.
    2. Validation: The resulting hash is checked against the federation's whitelist.
    3. Enforcement: If the hash is not in the whitelist, the contract deployment fails.

    Validation Layers

    • Consensus Rule: The system uses a full-validation consensus rule called AllowedCodeHashLogic. Full validation is required because the whitelist repository itself is updated via full-validation rules. This prevents issues during chain reorgs where a hash might be removed from the whitelist.
    • Mempool Validation: The mempool pre-validates incoming transactions using the same consensus rule. If a transaction's code hash is not whitelisted, it will not be considered for inclusion in a block.

    Note: A transaction might be accepted into the mempool but fail to be included in a block if the contract's code hash is removed from the whitelist between the time of mempool entry and the time of mining.