4 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;
}