[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/javascriptit/PacketCrypt/develop/src/Difficulty.c [Back]  [Original]

/**
 * (C) Copyright 2019
 * Caleb James DeLisle
 *
 * SPDX-License-Identifier: (LGPL-2.1-only OR LGPL-3.0-only)
 */
#include "Difficulty.h"
#include "Conf.h"
#include "config.h"

#include 
#include 

#ifdef __APPLE__
// Apple ships with openssl and then complains when you use it
// because they'd rather you use their framework instead
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include 

static void bnSetCompact(BIGNUM* bn, uint32_t nCompact)
{
    unsigned int nSize = nCompact >> 24;
    bool fNegative     =(nCompact & 0x00800000) != 0;
    unsigned int nWord = nCompact & 0x007fffff;
    if (nSize >= 8*(3-nSize);
        assert(BN_set_word(bn, nWord));
    }
    else
    {
        assert(BN_set_word(bn, nWord));
        assert(BN_lshift(bn, bn, 8*(nSize-3)));
    }
    BN_set_negative(bn, fNegative);
}

static uint32_t bnGetCompact(const BIGNUM* bn)
{
    unsigned int nSize = BN_num_bytes(bn);
    unsigned int nCompact = 0;
    if (nSize = 8;
        nSize++;
    }
    nCompact |= nSize > 56) & 0xff;
        n  24) & 0xff;
    pch[1] = (nSize >> 16) & 0xff;
    pch[2] = (nSize >> 8) & 0xff;
    pch[3] = (nSize) & 0xff;
    assert(BN_mpi2bn(pch, p - pch, out) == out);
}

static inline void assign(BIGNUM* out, const BIGNUM* val) {
    assert(BN_zero(out));
    assert(BN_add(out, out, val));
}

static inline void getEffectiveWork(
    BN_CTX* ctx,
    BIGNUM* workOut,
    const BIGNUM* blockWork,
    const BIGNUM* annWork,
    uint64_t annCount)
{
    if (BN_is_zero(annWork) || !annCount) {
        // This is work *required* so when there is no work and no announcements
        // that work is "infinite".
        bn256(workOut);
        return;
    }

    assign(workOut, blockWork);

    // workOut = workOut**3
    assert(BN_sqr(workOut, workOut, ctx));
    assert(BN_mul(workOut, workOut, blockWork, ctx));

#ifdef PCP2
    // difficulty *= 1024
    assert(BN_lshift(workOut, workOut, 10));
#endif

    // workOut /= annWork
    assert(BN_div(workOut, NULL, workOut, annWork, ctx));

    BIGNUM* bnAnnCount = BN_new();
    assert(bnAnnCount);
    setuint64(bnAnnCount, annCount);

#ifdef PCP2
    assert(BN_sqr(bnAnnCount, bnAnnCount, ctx));
#endif

    // workOut /= annCount
    assert(BN_div(workOut, NULL, workOut, bnAnnCount, ctx));

    BN_free(bnAnnCount);
}

uint32_t Difficulty_getEffectiveTarget(uint32_t blockTar, uint32_t annTar, uint64_t annCount)
{
    BN_CTX* ctx = BN_CTX_new();
    assert(ctx);

    BIGNUM* x = BN_new(); assert(x);
    BIGNUM* bnBlockWork = BN_new(); assert(bnBlockWork);
    BIGNUM* bnAnnWork = BN_new(); assert(bnAnnWork);

    bnSetCompact(x, blockTar);
    bnWorkForDiff(ctx, bnBlockWork, x);

    bnSetCompact(x, annTar);
    bnWorkForDiff(ctx, bnAnnWork, x);

    getEffectiveWork(ctx, x, bnBlockWork, bnAnnWork, annCount);

    bnDiffForWork(ctx, bnBlockWork, x);
    uint32_t res = bnGetCompact(bnBlockWork);

    BN_free(x);
    BN_free(bnBlockWork);
    BN_free(bnAnnWork);
    BN_CTX_free(ctx);

    return res > 0x207fffff ? 0x207fffff : res;
}

uint64_t Difficulty_getHashRateMultiplier(uint32_t annTar, uint64_t annCount)
{
    BN_CTX* ctx = BN_CTX_new();
    assert(ctx);

    BIGNUM* x = BN_new(); assert(x);
    BIGNUM* bnAnnWork = BN_new(); assert(bnAnnWork);
    BIGNUM* bnAnnCount = BN_new(); assert(bnAnnCount);

    bnSetCompact(x, annTar);
    bnWorkForDiff(ctx, bnAnnWork, x);

    setuint64(bnAnnCount, annCount);
#ifdef PCP2
    assert(BN_sqr(bnAnnCount, bnAnnCount, ctx));
#endif
    assert(BN_mul(x, bnAnnWork, bnAnnCount, ctx));

#ifdef PCP2
    // Difficulty jumps by 1024
    assert(BN_rshift(x, x, 10));
#endif

    uint64_t out = BN_get_word(x);

    BN_free(bnAnnCount);
    BN_free(bnAnnWork);
    BN_free(x);
    BN_CTX_free(ctx);

    return out;
}

static inline uint32_t degradeAnnouncementTarget2(uint32_t annTar, uint32_t annAgeBlocks)
{
    if (annAgeBlocks < Conf_PacketCrypt_ANN_WAIT_PERIOD) { return 0xffffffff; }
    if (annAgeBlocks == Conf_PacketCrypt_ANN_WAIT_PERIOD) { return annTar; }
    annAgeBlocks -= Conf_PacketCrypt_ANN_WAIT_PERIOD;
    BIGNUM* bnAnnTar = BN_new(); assert(bnAnnTar);
    bnSetCompact(bnAnnTar, annTar);
    assert(BN_lshift(bnAnnTar, bnAnnTar, annAgeBlocks));
    uint32_t out = 0xffffffff;
    if (BN_num_bits(bnAnnTar) < 256) {
        out = bnGetCompact(bnAnnTar);
    }
    BN_free(bnAnnTar);
    return out > 0x207fffff ? 0xffffffff : out;
}

uint32_t Difficulty_degradeAnnouncementTarget(uint32_t annTar, uint32_t annAgeBlocks)
{
#ifdef PCP2
    return degradeAnnouncementTarget2(annTar, annAgeBlocks);
#endif
    if (annAgeBlocks < Conf_PacketCrypt_ANN_WAIT_PERIOD) { return 0xffffffff; }
    annAgeBlocks -= (Conf_PacketCrypt_ANN_WAIT_PERIOD - 1);
    BN_CTX* ctx = BN_CTX_new(); assert(ctx);
    BIGNUM* bnAnnTar = BN_new(); assert(bnAnnTar);
    BIGNUM* bnAnnWork = BN_new(); assert(bnAnnWork);
    BIGNUM* bnAnnAgeBlocks = BN_new(); assert(bnAnnAgeBlocks);
    setuint64(bnAnnAgeBlocks, annAgeBlocks);

    bnSetCompact(bnAnnTar, annTar);
    bnWorkForDiff(ctx, bnAnnWork, bnAnnTar);
    assert(BN_div(bnAnnWork, NULL, bnAnnWork, bnAnnAgeBlocks, ctx));
    bnDiffForWork(ctx, bnAnnTar, bnAnnWork);
    uint32_t out = bnGetCompact(bnAnnTar);

    BN_free(bnAnnTar);
    BN_free(bnAnnWork);
    BN_free(bnAnnAgeBlocks);
    BN_CTX_free(ctx);

    // if out > 0x207fffff then it rounds to zero, meaning the announcement cannot be mined
    return out > 0x207fffff ? 0xffffffff : out;
}

// IsAnnMinDiffOk is kind of a sanity check to make sure that the miner doesn't provide
// "silly" results which might trigger wrong behavior from the diff computation
bool Difficulty_isMinAnnDiffOk(uint32_t target)
{
    if (target == 0 || target > 0x20ffffff) {
        return false;
    }
#ifdef PCP2
    if (target > 0x207fffff) { return false; }
#endif
    BN_CTX* ctx = BN_CTX_new(); assert(ctx);
    BIGNUM* bnTar = BN_new(); assert(bnTar);
    BIGNUM* bnWork = BN_new(); assert(bnWork);
    BIGNUM* bnMax = BN_new(); assert(bnMax);
    bnSetCompact(bnTar, target);
#ifdef PCP2
    if (BN_is_zero(bnTar) || BN_is_negative(bnTar)) { return false; }
#endif
    bnWorkForDiff(ctx, bnWork, bnTar);
    if (BN_is_zero(bnWork)) { return false; }
    bn256(bnMax);
    if (BN_cmp(bnWork, bnMax) >= 0) { return false; }
    BN_free(bnTar);
    BN_free(bnWork);
    BN_free(bnMax);
    BN_CTX_free(ctx);
    return true;
}

Web Proxy Viewer  |  New URL  |  Original Page