# 区块链学习(4) 难度目标调整

1、最大难度目标

0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

2、难度目标的存储

target = coefficient*2^(8*(exponent-3))

0x00FFFF * 2^(8*(0x1D-3)) = 0x00000000FFFF0000000000000000000000000000000000000000000000000000

(8*(exponent-3))/4 = 2*(exponent-3) 可以得出十六进制难度系数后面有多少个0。
0x1D00FFFF 展开后 系数00FFFF后面可以算出有52个0。

3、难度目标的调整

4、难度目标的计算

btc.com不太稳定，有时会返回失败。可以多试几次。

// xmain.c
// by maxzero
#include "xutils.h"

int grab_block_info(int block_num, char *block_buf, int block_len)
{
FILE* f = NULL;
int   n = 0;
int   r = 0;

char  url[1024];
char* buf = NULL;
int   len = 0;

memset(url, 0x00, sizeof(url));
sprintf(url, "curl -s https://chain.api.btc.com/v3/block/%d", block_num);
f = popen(url, "r");

buf = block_buf;
len = block_len;

memset(buf, 0x00, len);
n = fread(buf, 1, len, f);
if (n <= 0) {
xprint_err("fread() failed. n=%d\n", n);
r = -1;
}

pclose(f);
return r;
}

int scan_block_bits(int begin, int end, int interval)
{
int i = 0;

int   len = 1*1024*1024*sizeof(char);
char *buf = (char*)malloc(len);
char  temp[32];

for (i=begin; i<=end; i+=interval) {
printf("block=%06d ", i);
sleep(1);
if (0 != grab_block_info(i, buf, len)) {
continue;
}

memset(temp, 0x00, sizeof(temp));
if (-1 != xkey_value_parser(buf, "\"timestamp\":", ",", temp, sizeof(temp))) {
printf("timestamp=%s ", temp);
}

memset(temp, 0x00, sizeof(temp));
if (-1 != xkey_value_parser(buf, "\"bits\":", ",", temp, sizeof(temp))) {
uint32_t nbits = atoi(temp);
printf("nbits=%s 0x%x ", temp, nbits);
}

memset(temp, 0x00, sizeof(temp));
if (-1 != xkey_value_parser(buf, "\"difficulty\":", ",", temp, sizeof(temp))) {
printf("difficulty=%s", temp);
}

printf("\n");
}

free(buf);
return 0;
}

int main(int argc, char* argv[])
{
/*扫描block 0-552383,间隔2016*/
scan_block_bits(0, 552383, 2016);
return 0;
}

gcc xmain.c xutils.c
./a.out
block=000000 timestamp=1231006505 nbits=486604799 0x1d00ffff difficulty=1
block=002016 timestamp=1233063531 nbits=486604799 0x1d00ffff difficulty=1
block=004032 timestamp=1234466190 nbits=486604799 0x1d00ffff difficulty=1
block=006048 timestamp=1235966513 nbits=486604799 0x1d00ffff difficulty=1
block=008064 timestamp=1237508786 nbits=486604799 0x1d00ffff difficulty=1
block=010080 timestamp=1239055463 nbits=486604799 0x1d00ffff difficulty=1
block=012096 timestamp=1240599098 nbits=486604799 0x1d00ffff difficulty=1
block=014112 timestamp=1242098425 nbits=486604799 0x1d00ffff difficulty=1
block=016128 timestamp=1243737085 nbits=486604799 0x1d00ffff difficulty=1
block=018144 timestamp=1246051973 nbits=486604799 0x1d00ffff difficulty=1
block=020160 timestamp=1248481816 nbits=486604799 0x1d00ffff difficulty=1
block=022176 timestamp=1252069298 nbits=486604799 0x1d00ffff difficulty=1
block=024192 timestamp=1254454028 nbits=486604799 0x1d00ffff difficulty=1
block=026208 timestamp=1257002900 nbits=486604799 0x1d00ffff difficulty=1
block=028224 timestamp=1259358667 nbits=486604799 0x1d00ffff difficulty=1
block=030240 timestamp=1261130161 nbits=486604799 0x1d00ffff difficulty=1
block=032256 timestamp=1262153464 nbits=486594666 0x1d00d86a difficulty=1.1828995343128408
block=034272 timestamp=1263250117 nbits=486589480 0x1d00c428 difficulty=1.3050621315915245
block=036288 timestamp=1264424879 nbits=486588017 0x1d00be71 difficulty=1.3442249707710294
...

block-032256->nbits=block-032255->nbits*((block-032255->timestamp-block-030240->timestamp)/2016*10*60)
block-032255->nbits要先转换为256位的整数，计算完后再压缩位32位的整数，最终得到block-032256->nbits。

// xmain.cpp
// by maxzero
#include <stdio.h>
#include "arith_uint256.h"

uint32_t difficulty_compute(int64_t time_span, uint32_t nbits_prev)
{
uint32_t nbits = 0;
arith_uint256 diff;

diff.SetCompact(nbits_prev);
diff *= time_span;
diff /= (2016*10*60);
nbits = diff.GetCompact();

printf("0x%x\n", nbits);
printf("%s\n", diff.GetHex().c_str());
return nbits;
}

//block=030240 timestamp=1261130161 nbits=486604799 0x1d00ffff difficulty=1
//block=032255 timestamp=1262152739 nbits=486604799 0x1d00ffff difficulty=1
//block=032256 timestamp=1262153464 nbits=486594666 0x1d00d86a difficulty=1.1828995343128408
int main(int argc, char* argv[])
{
difficulty_compute((1262152739-1261130161), 0x1d00ffff);
return 0;
}


g++ xmain.cpp arith_uint256.cpp uint256.cpp utilstrencodings.cpp -std=gnu++11 -I./

#依赖的文件信息
#这些都可以在bitcoin的源码找到
#https://github.com/bitcoin/bitcoin/tree/master/src

├── a.out
├── arith_uint256.cpp
├── arith_uint256.h
├── compat
│   ├── byteswap.h
│   └── endian.h
├── crypto
│   ├── common.h
│   └── sha256.h
├── xmain.cpp
├── sha256.cpp
├── tinyformat.h
├── uint256.cpp
├── uint256.h
├── utilstrencodings.cpp
└── utilstrencodings.h

./a.out
0x1d00d86a #压缩后的nbits
00000000d86a528bc8bc8bc8bc8bc8bc8bc8bc8bc8bc8bc8bc8bc8bc8bc8bc8b #未压缩的nbits


bitcoin中关于难度调整的代码在pow.cpp中

unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
if (params.fPowNoRetargeting)
return pindexLast->nBits;

// Limit adjustment step
// nActualTimespan 之前2016个区块花费时长(单位秒)
int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
// params.nPowTargetTimespan 2016*10*60 14天
// nActualTimespan 的取值范围限定为 3.5天-56天
if (nActualTimespan < params.nPowTargetTimespan/4)
nActualTimespan = params.nPowTargetTimespan/4;
if (nActualTimespan > params.nPowTargetTimespan*4)
nActualTimespan = params.nPowTargetTimespan*4;

// Retarget
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
// 计算新的难度值
arith_uint256 bnNew;
bnNew.SetCompact(pindexLast->nBits);
bnNew *= nActualTimespan;
bnNew /= params.nPowTargetTimespan;

// bnNew 不能大于最大难度目标
if (bnNew > bnPowLimit)
bnNew = bnPowLimit;

return bnNew.GetCompact();
}

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客