6 months ago
//首先调用函数仓库,函数仓库分为三种:1、操作系统的函数仓库;2、标准函数仓库;3、第三方机构或个人写的函数仓库。
其中,stdio.h(标准输出和输入的函数库)、stdlib.h(内存分配的函数库)和 string.h(字符串和内存管理函数库)都是三个标准且常用的函数仓库。
tomcrypt.h是第三方机构函数库,#define TFM_DESE是为了激活tomcrypt.h内的函数用的,是调用此函数的标准写法。

#define TFM_DESC
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "tfm.h"
#include "tomcrypt.h"

//这里是为了定义rmd160哈希函数,输出的结果是20bytes的16进制形式。
char *get_rmd160(char *buffer, int size)
{
   hash_state resource;
   char *digest;

   digest = malloc(20);
   rmd160_init(&resource);
   rmd160_process(&resource, buffer, size);
   rmd160_done(&resource, digest);

   return digest;
}

//这里是为了定义sha256哈希函数,输出的结果是32bytes的16进制形式。
char *get_sha256(char *buffer, int size)
{
   hash_state resource;
   char *digest;

   digest = malloc(32);
   sha256_init(&resource);
   sha256_process(&resource, buffer, size);
   sha256_done(&resource, digest);

   return digest;
}

//这里是定义base58check encoding的用法,目的是将生字节转换成base58字符串。
因为在直接调用这个函数方法时失败,所以将源代码粘贴到这里,所以代码看起来很长。
static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

// Thanks to Luke Dashjr.

int b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
{
   const uint8_t *bin = data;
   int carry;
   ssize_t i, j, high, zcount = 0;
   size_t size;
   
   while (zcount < binsz && !bin[zcount])
      ++zcount;
   
   size = (binsz - zcount) * 138 / 100 + 1;
   uint8_t buf[size];
   memset(buf, 0, size);
   
   for (i = zcount, high = size - 1; i < binsz; ++i, high = j)
   {
      for (carry = bin[i], j = size - 1; (j > high) || carry; --j)
      {
         carry += 256 * buf[j];
         buf[j] = carry % 58;
         carry /= 58;
      }
   }
   
   for (j = 0; j < size && !buf[j]; ++j);
   
   if (*b58sz <= zcount + size - j)
   {
      *b58sz = zcount + size - j + 1;
      return 0;
   }
   
   if (zcount)
      memset(b58, '1', zcount);
   for (i = zcount; j < size; ++i, ++j)
      b58[i] = b58digits_ordered[buf[j]];
   b58[i] = '\0';
   *b58sz = i + 1;
   
   return 1;
}

//这里定义了scan函数用法,目的是为了获得一个物件的总长度。
因为指针指向了最开始,并且转换成了整数类型,所以代表的是这个物件的头部内容的数值,即它的总长度。
int scan(char *source)
{
   int *size;

   size = (int *) source;

   return *size;
}

//这里定义了生成私钥的用法,ecc_make_key就是生成私钥的函数,
而ecc_export是将生字节的私钥转换成了字符串的私钥,即输出的私钥是字符串形式的。
unsigned char *get_private(unsigned int *length)
{
   prng_state random;
   ecc_key key;
   unsigned char *buffer;

   buffer = malloc(*length = 1000);
   ecc_make_key(&random, find_prng("sprng"), 32, &key);
   ecc_export(buffer, length, PK_PRIVATE, &key);

   return buffer;
}

//这里定义了生成公钥的用法,ecc_import先将私钥引进来,ecc_export是将私钥转换成公钥。
unsigned char *get_public(unsigned int *length, unsigned char *private)
{
   ecc_key key;
   unsigned char *buffer;

   ecc_import(private, *length, &key);
   buffer = malloc(*length = 1000);
   ecc_export(buffer, length, PK_PUBLIC, &key);

   return buffer;
}

//这里定义了读文件的用法,先打开可读的一个文件,到最后面量出这个文件的总长度,
再回到最开始的位置,之后给其分配内存空间,将文件内容放进这个内存空间,然后关闭文件,返回文件的内容。
char *read_file(char *path, int *length) {

   FILE *file;
   char *contents;

   file = fopen(path, "r+");
   fseek(file, 0, SEEK_END);
   *length = ftell(file);
   fseek(file, 0, SEEK_SET);

   contents = malloc(*length + 1);
   fread(contents, 1, *length, file);
   fclose(file);

   return contents;
}

//这里定义了写文件的用法。
void write_file(char *path, char *substance, int length)
{
   FILE *file;

   file = fopen(path, "w");
   fwrite(substance, 1, length, file);
   fclose(file);
}

//这里定义了string_create的用法,目的是为了得到一个属性的长度和这个属性的内容。
char *string_create(char *old, int length)
{
   char *new;
   int *_6157;

   new = malloc(length + 4) + 4;
   memcpy(new, old, length);

   _6157 = (int *) (new - 4);
   *_6157 = length;

   return new;
}

//这里定义了string_create_improper的用法,目的是为了得到一个属性的长度和这个属性的内容,
跟上面的string_create的区别在于:strlen()这个函数只能测量字符串的长度,不能测量生字节的长度。
char *string_create_improper(char *old)
{
   char *new;
   int *_7193;

   new = malloc(strlen(old) + 4) + 4;
   memcpy(new, old, strlen(old));

   _7193 = (int *) (new - 4);
   *_7193 = strlen(old);

   return new;
}

//这里定义了string_measure的用法,目的是为了得到一个属性的长度,而scan是为了得到一个物件的长度。
int string_measure(char *buffer)
{
   int *_4721;

   _4721 = (int *) (buffer - 4);

   return *_4721;
}

//这里定义了构成输入的用法,将输入的几个属性有序地拼接在一起。
uint8_t *create_input(uint32_t index, uint8_t *public, uint8_t *signature, uint8_t *transaction)
{
   uint8_t *result;
   uint32_t a, b, c;

   result = malloc(48 + string_measure(public) + string_measure(signature));

   a = 48 + string_measure(public) + string_measure(signature);
   b = string_measure(public);
   c = string_measure(signature);

   memcpy(result, &a, 4);
   memcpy(result + 4, &index, 4);
   memcpy(result + 8, &b, 4);
   memcpy(result + 12, public, b);
   memcpy(result + 12 + b, &c, 4);
   memcpy(result + 16 + b, signature, c);
   memcpy(result + 16 + b + c, transaction, 32);
   return result;
}

//这里定义了构成输出的用法,将输出的几个属性有序地拼接在一起。
uint8_t *create_output(uint8_t *address, uint64_t amount)
{
   uint8_t *result;
   uint32_t a, b;

   result = malloc(16 + string_measure(address));

   a = 16 + string_measure(address);
   b = string_measure(address);

   memcpy(result, &a, 4);
   memcpy(result + 4, &b, 4);
   memcpy(result + 8, address, b);
   memcpy(result + 8 + b, &amount, 8);

   return result;
}

//这里定义了构成head的用法,将head的几个属性有序地拼接在一起。
uint8_t *create_head(uint8_t *current, uint32_t nonce, uint8_t *previous, uint8_t *target, uint32_t time, uint32_t valence)
{
   uint8_t *result;

   result = malloc(108);

   memcpy(result, current, 32);
   memcpy(result + 32, &nonce, 4); 
   memcpy(result + 36, previous, 32);
   memcpy(result + 68, target, 32);
   memcpy(result + 100, &time, 4);
   memcpy(result + 104, &valence, 4);

   return result;
}

//这里是主代码部分,首先将公钥生成了地址,根据输入和输出生成了transaction这个物件,
根据transaction又生成了head这个物件,根据transaction和head最后生成了创世block,
将这个创世块写进了一个叫1.block的文件中。
int main(int count, char **arguments)
{
//这三行是配合tomcrypt.h这个函数库的,是调用这个函数的标准写法。
   ltc_mp = tfm_desc;
   register_prng(&sprng_desc);
   register_hash(&sha256_desc);

//下面是用公钥生成地址的过程,可以参考bitcoinwiki上的流程图。
   int X, Y, Z;
   char *AA, *BB, *CC;

//打开一个公钥文件,然后将base64字符串形式的公钥转换成生字节形式的公钥(base64_decode就是起到这个作用的),
然后进行sha256哈希和rmd160哈希,得到CC。
   AA = read_file("wangjingru.public", &X);
   BB = malloc(1000);
   Y = 1000;
   base64_decode(AA, X, BB, &Y);
   CC = get_sha256(BB, Y);
   CC = get_rmd160(CC, 32);

//在CC前面增加网络版本号137,然后再进行两次sha256哈希,两次哈希是为了增加安全性,然后得到FF。
   char *FF = malloc(21);
   FF[0] = 137;
   memcpy(FF + 1, CC, 20);
   FF = get_sha256(FF, 21);
   FF = get_sha256(FF, 32);

//将FF的前面四个字节拼接到CC的后面,得到DD。
   char *DD = malloc(25);
   DD[0] = 137;
   memcpy(DD + 1, CC, 20);
   memcpy(DD + 21, FF, 4);

//将DD进行base58check encoding转换,将生字节转换成base58字符串地址。
   char *result = malloc(1000);
   int size = 1000;
   b58enc(result, &size, DD, 25);
   printf("%s%c", result, 10);

   // base64 decode
   // sha256
   // ripemd
   // sha256 sha256
   // get four

//这里是为了产生transaction的,将输入和输出拼接起来。
   char *low=result;
   low = malloc(32);

   memset(low, 0, 32);
   char *input, *output;
   char *transaction;

   int A, B, C;

   input = create_input(0, string_create(0, 0), string_create(0, 0), low);
   output = create_output(string_create_improper("xJguydL8ujwPW6uKScjkZJeg49JnLvAG4h"), 5000000000ULL);
   
   A = 12 + scan(input) + scan(output);
   B = 1;
   C = 1;

   transaction = malloc(12 + scan(input) + scan(output));
   memcpy(transaction, &A, 4);
   memcpy(transaction + 4, &B, 4);
   memcpy(transaction + 8, &C, 4);
   memcpy(transaction + 12, input, scan(input));
   memcpy(transaction + 12 + scan(input), output, scan(output));

//这里是为了生成head的,利用上面生成的transaction生成merkle根,然后定义目标高度,目标最高,即难度系数最低。
   char *previous = malloc(32);
   memset(previous, 0, 32);
   char *target = malloc(32);
   memset(target, 255, 32);
   target[0] = 0;
   target[1] = 0;
   char *head = create_head(get_sha256(transaction, scan(transaction)), 0, previous, target, time(0), 1);

   char *block = malloc(108 + scan(transaction));
   memcpy(block, head, 108);
   memcpy(block + 108, transaction, scan(transaction));

//然后将head和transaction拼接起来成为一个区块,写进1.block的文件中,即我们的创世块被创造出来了。
   write_file("1.block", block, 108 + scan(transaction));

   // a = malloc(32); memset(a, 0, 32);
   // a = malloc(32); memset(a, 255, 32);

   // current nonce previous target time valence

   // sha256(transaction)
   // 0
   // 00000000000000000...
   // yikaishi, nandu shi zui jiandan de
   // 2016 caihui tiaozheng

   // time();
   // 1

   return 0;   
}

← 哈希文件中的每个名字 nano编辑器常用快捷键 →
 
comments powered by Disqus