Skip to content
Permalink
Browse files

sserver: Implement BEAM hard fork #321321 (BEAM Hash II).

  • Loading branch information...
SwimmingTiger committed Aug 7, 2019
1 parent 747e776 commit 5c835f587de874d4fe0c54da2bfc80c1421b1280
@@ -25,7 +25,7 @@ namespace beam

struct PoW
{
// equihash parameters.
// equihash parameters.
// Parameters recommended by BTG are 144/5, to make it asic-resistant (~1GB average, spikes about 1.5GB). On CPU solve time about 1 minutes
// The following are the parameters for testnet, to make it of similar size, and much faster solve time, to test concurrency and difficulty adjustment
static const uint32_t N = 150;
@@ -45,8 +45,8 @@ namespace beam
NonceType m_Nonce; // 8 bytes. The overall solution size is 96 bytes.
Difficulty m_Difficulty;

bool IsValid(const void* pInput, uint32_t nSizeInput) const;
bool ComputeHash(const void* pInput, uint32_t nSizeInput, ECC::Hash::Value &hv) const;
bool IsValid(const void* pInput, uint32_t nSizeInput, uint32_t) const;
bool ComputeHash(const void* pInput, uint32_t nSizeInput, ECC::Hash::Value &hv, uint32_t) const;

private:
struct Helper;
@@ -54,6 +54,24 @@ namespace beam
return memis0(a.m_pData, Raw::nBytes - (s_MantissaBits >> 3));
}

bool Difficulty::get_Target(ECC::uintBig& hv) const
{
hv = Zero;

if (m_Packed > s_Inf)
return false; // invalid

Raw rDiff;
Unpack(rDiff);

static_assert(!(s_MantissaBits & 7), ""); // fix the following code lines to support non-byte-aligned mantissa size
uintBig_t<Raw::nBytes + (s_MantissaBits >> 3)> rMax;
memset(rMax.m_pData, 0xff, rMax.nBytes);

hv.SetDiv(rMax, rDiff);
return true;
}

void Difficulty::Unpack(Raw& res) const
{
res = Zero;
@@ -186,7 +204,7 @@ namespace beam
}
}
}

void Difficulty::Pack(const Raw& ref) {
BigFloat x = BigFloat(ref);

@@ -33,6 +33,7 @@ namespace beam
static const uint32_t s_Inf = (s_MaxOrder + 1) << s_MantissaBits;

bool IsTargetReached(const ECC::uintBig&) const;
bool get_Target(ECC::uintBig&) const; // more expensive to calculate. Use to test many variants for the same target

void Unpack(Raw&) const;
void Pack(const Raw&);
@@ -343,4 +343,34 @@ namespace beam {
memset0(pDst0 + nDst, nBytes);
}

void uintBigImpl::_Div(uint8_t* pDst, uint32_t nDst, const uint8_t* pA, uint32_t nA, const uint8_t* pB, uint32_t nB, uint8_t* pMul, uint8_t* pTmp)
{
memset0(pDst, nDst);
memset0(pMul, nA);

uint32_t nOrder = _GetOrder(pB, nB);
if (nOrder > (nA << 3))
return;

for (uint32_t nShift = 1 + std::min((nA << 3) - nOrder, (nDst << 3) - 1); nShift--; )
{
_ShiftLeft(pTmp, nA, pB, nB, nShift);
_Inc(pTmp, nA, pMul, nA);

if (_Cmp(pMul, nA, pTmp, nA) > 0)
continue; // overflow

if (_Cmp(pA, nA, pTmp, nA) < 0)
continue; // exceeded

memcpy(pMul, pTmp, nA);
pDst[nDst - (nShift >> 3) - 1] |= (1 << (7 & nShift));
}

#ifndef NDEBUG
_Mul(pTmp, nA, pB, nB, pDst, nDst);
assert(!_Cmp(pTmp, nA, pMul, nA));
#endif // NDEBUG
}

} // namespace beam
@@ -103,6 +103,7 @@ namespace beam
static void _ShiftRight(uint8_t* pDst, uint32_t nDst, const uint8_t* pSrc, uint32_t nSrc, uint32_t nBits);
static void _ShiftLeft(uint8_t* pDst, uint32_t nDst, const uint8_t* pSrc, uint32_t nSrc, uint32_t nBits);

static void _Div(uint8_t* pDst, uint32_t nDst, const uint8_t* pA, uint32_t nA, const uint8_t* pB, uint32_t nB, uint8_t* pMul, uint8_t* pBuf);
};

template <uint32_t nBytes_>
@@ -283,6 +284,22 @@ namespace beam
_ShiftLeft(res.m_pData, res.nBytes, m_pData, nBytes, nBits);
}

template <uint32_t nBytesA, uint32_t nBytesB>
void SetDiv(const uintBig_t<nBytesA>& a, const uintBig_t<nBytesB>& b)
{
// Calculates a/b. Rounding to a smaller side. if b = 0, then the result is max value. Same if the type is too small to hold the full result
// In other words, the result is the maximum value for which (*this * b <= a)
uintBig_t<nBytesA> mul;
SetDiv(a, b, mul);
}

template <uint32_t nBytesA, uint32_t nBytesB>
void SetDiv(const uintBig_t<nBytesA>& a, const uintBig_t<nBytesB>& b, uintBig_t<nBytesA>& mul)
{
uintBig_t<nBytesA> tmp;
_Div(m_pData, nBytes, a.m_pData, a.nBytes, b.m_pData, b.nBytes, mul.m_pData, tmp.m_pData);
}

// helper, for uniform random generation within specific bounds
struct Threshold
{
@@ -0,0 +1,69 @@
// Copyright (c) 2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_CRYPTO_COMMON_H
#define BITCOIN_CRYPTO_COMMON_H

#if defined(HAVE_CONFIG_H)
#include "bitcoin-config.h"
#endif

#include <stdint.h>
#include <assert.h>

#if defined(_MSC_VER) || defined(__APPLE__) || defined(__ANDROID__)
#include "compat/endian.h"
#endif

uint16_t static inline ReadLE16(const unsigned char* ptr)
{
return le16toh(*((uint16_t*)ptr));
}

uint32_t static inline ReadLE32(const unsigned char* ptr)
{
return le32toh(*((uint32_t*)ptr));
}

uint64_t static inline ReadLE64(const unsigned char* ptr)
{
return le64toh(*((uint64_t*)ptr));
}

void static inline WriteLE16(unsigned char* ptr, uint16_t x)
{
*((uint16_t*)ptr) = htole16(x);
}

void static inline WriteLE32(unsigned char* ptr, uint32_t x)
{
*((uint32_t*)ptr) = htole32(x);
}

void static inline WriteLE64(unsigned char* ptr, uint64_t x)
{
*((uint64_t*)ptr) = htole64(x);
}

uint32_t static inline ReadBE32(const unsigned char* ptr)
{
return be32toh(*((uint32_t*)ptr));
}

uint64_t static inline ReadBE64(const unsigned char* ptr)
{
return be64toh(*((uint64_t*)ptr));
}

void static inline WriteBE32(unsigned char* ptr, uint32_t x)
{
*((uint32_t*)ptr) = htobe32(x);
}

void static inline WriteBE64(unsigned char* ptr, uint64_t x)
{
*((uint64_t*)ptr) = htobe64(x);
}

#endif // BITCOIN_CRYPTO_COMMON_H

This file was deleted.

0 comments on commit 5c835f5

Please sign in to comment.
You can’t perform that action at this time.