Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
jonano614 committed May 22, 2018
2 parents fd36dc6 + d1ac258 commit e3b0791
Show file tree
Hide file tree
Showing 14 changed files with 377 additions and 122 deletions.
167 changes: 167 additions & 0 deletions Protocol-cn.md
@@ -0,0 +1,167 @@
# XDAG加密货币协议
#### Version 0.3.1 Apirl 6, 2018

## 1.名词解释

**区快地址** - 区块hash截取后的base64编码.

**金额** - XDAG的数量,以Cheato为单位,类似比特币的Santoshi.

**区块** - Dagger的基本结构, 每个区块定长512字节, 结构定义在第二部分介绍.

**** - 一个块的序列,其中每个块被前一个块引用.

**Cheato** - 一个XDAG包括2^32个Cheato.

**Dagger元年** - Unix格式:0x5A500000 ,也就是2018年1月5日.

**区块难度** - (2^128-1)/(hash_little / 2^160), hash_little = 小端字节序(hash(block)), hash_little大小为256 bits(32 bytes).

**链难度** - 链上区块的难度之和.

**Hash** - 采用双sha256哈希算法, hash(block) = sha256(sha256(block)).

**主块** - 主链上的任何区块.

**主链** - 难度最大的链称为主链.

**链接** - 如果A具有类型2或3的字段,其中包含块B的截断散列,请参第二章.

**引用** - 如果从区块A到区块B是一段连续的区块组成,则称区块B被区块A引用.

**i-引用** - 如果区块A的第i个域连接到区块C,并且区块C引用区块B,则称区块B是区块A的i-引用.

**分离链** - 链上的区块属于不同的时间片.

**最短链** - 一个从区块A到区块B的链,每个区块都是i-引用B。i越小,链越短.

**时间片** - 每64秒一个时间片,时间为Unix格式,低6bits等于0.

**区块时间** - 区块时间记录在区块头信息里,从1970年1月1号开始,单位是1/1024秒.

**交易** - 交易即区块.

**hash截断** - hash小端字节序表示,取最低24个字节.


## 2.区块

一个区块有16个字段,每个字段32个字节,每个字段type可能为0到15,一般区块,第0个字段type必须是1;伪块,第0个字段必须是类型0。有关传输用的伪块,详看第5章

字段的类型0-15:

0 随机数, 32字节.

1 区块头. 结构如下:
- 64-bit 传输层头, 在计算区块散列的时候,这个头信息要全部设置为0;
- 64-bit 小端字节序, 包括字段类型0..15. 每个类型4 bits. 字段0的类型编码为低4位.
- 64-bit 小端字节序, 区块的时间.
- 64-bit 小端字节序, 交易的手续费.

2 交易的输入. 连接到另外一个区块B.
结构如下:
- 192-bit 区块B的hash截断.
- 64-bit 小端字节序, 区块被应用后的金额.


3 交易的输出. 连接到其他区块.
结构如下:
- 192-bit 区块B的hash截断.
- 64-bit 小端字节序, 区块被应用后的金额.

4 输入签名的一半. 输入签名由两个type为4的字段组成.
第一个字段是r,第二个字段是s,这两个值都是从ECDSA的签名算法获得.
通过以下摘要得出的ECDSA签名, 并通过相应的私钥进行签名.
摘要是:
hash(modified_block # key_prefix_byte # public_key)
其中:
- # 是连接符号
- modified_block 是去除块中的输入签名与输出签名字段,由零填充.
- key_prefix_byte 如果公钥是偶数,0x02, 如果公钥是奇数,0x03.
- public_key - 公钥, 32 bytes.

5 输出签名的一半. 结构与输入签名一样. 参考第3章 . 输入与输出签名的区别.

6 偶数公钥. 该字段包含ECDSA的编号x公共密钥,如果数字y是偶数.

7 奇数公钥. 该字段包含ECDSA的编号x公共密钥,如果数字y是奇数.

8 - 15 留给未来的使用.


## 3.算法

每一个区块都是一个交易. 一个交易个可能有多个输入、输出、公钥、 输入和输出的签名, 还有手续费. 如果满足以下条件,则区块是有效的:

- 区块的产生时间不小于Dagger元年(2018-01-06 22:45:20);
- 区块的输入、输出时间小于区块A的产生时间;
- 区块的每个输入或者输出必须是合法的区块;
- 区块的所有输入金额之和必须小于2的64次方;
- 区块的所有输出金额加上手续费必须小于2的64次方;
- 如果至少有一个输入大于所有输入的和,则必须不少于所有输出之和加上手续费;否则,所有输出的和必须为零;
- 对于区块A的每个输入B,在块A中有公钥K和输入或输出签名S,在块B中有输出签名T,使得使用密钥K,从块A获得签名S,使用相同密钥K,从块B获得签名T(非正式描述:只有块B的所有者才能从它提取资金)
- 输出签名字段的数目必须是偶数,而输入签名字段的数目可能是奇数;在这种情况下,最后一个输入签名字段可以被用作随机数,可以在不重新签名的情况下修改该字段.

任何时刻,只有一个主链 (看 [1.名词解释](#1.名词解释)). 主链上的区块称为主块. 每个主块属于不同的时间片. 也就是说,在一个时间片内,有1个或0个主块. 每个主块被挖出来时,会奖被奖励. 在第一个四年,奖励1024个XDAG。第二个四年,奖励512个XDAG, 之后每四年,奖励减半,XDAG的产出总量大约40亿

区块按照下面的规则排序:

1. 如果区块A被某个主块M引用,但是区块B没被主块M引用,则区块A优先区块B.
2. 如果区块A和区块B相等,并且区块M是最小的被引用区块,并且区块C是M到A或者M到B的最小链上的公共块,如果A是C的i-引用,B是C的j-引用,并且i小于j的话,区块A优先区块B.
3. 如果区块A和区块B在条件1/2下都相等,并且区块A被区块B引用,区块A优先区块B,交易使用上述规则进行。如果上述规则无法适用,该交易无效.

交易使用上述规则进行, 如果上述规则无法适用,该交易无效.
每个区块拥有自己的XDAG金额.一开始的情况下是0, 但是在如下情况下,金额会变化:

1. 如果区块A是被挖出的区块, 区块A的金额会加上主块奖励.
2. 如果区块A作为区块B的输入,区块A的金额会减去区块B的相应的输出金额.
3. 如果区块A作为区块B的输出, 在这种情况下区块A的金额会增加区块B的相应的输入金额
4. 如果区块A是区块B连接中的最小的区块(按照上述规则),则区块A的金额会增加区块B的手续费.
5. 如果区块A的输入总和大于输出总额以及费用,则区块A的金额是两者的差额.

一个交易能合法验证,必须满足以下条件:

1. 对于区块A中的所有输入,要小于对于区块金额.
2. 区块A中所有输入加区块A本身的金额的大小必须大于所有输出以及手续费之和.

因为每个区块有金额,所以本身也就是一个账户.用户如果拥有区块A中的输出的签名的私钥,则该用户拥有该区块A的账户.用户可以通过地址访问他的账户.区块地址是针对区块截断散列的base64编码。地址是32字节的字符串,包括字符:A-Z, a-z, 0-9, /, +.用户可以在系统中从他自己的账户中提取金额并且转账给一个有效的区块.

## 4.加密与安全

签名算法,使用openssl实现中的标准ECDSA签名.椭圆曲线是Secp256k1.私钥长度为32个字节,公钥的长度为32字节(椭圆曲线上的点的x坐标)加上(椭圆曲线上的点的y坐标).签名是64个字节,由两个字段组成.这两个字段别是ECDSA签名算法中的r和s.
私钥存在wallet.dat文件中,这个文件和xdag可执行程序在同一目录.每个私钥长度32个字节, 公钥不保存,因为公钥可以从私钥计算得出.当用户第一次启动xdag程序时,要求用户提供一串随机字符.这些字符会作为随机生成器的种子.这些字符存在dnet_key.dat文件中.每次xdaga启动时,这些字符会参与随机数生成, 所有的私钥用这些字符生成。

## 5.传输层

Dagger节点利用传输协议进行区块的交换.区块的前8个字节会用做传输协议特定的信息. 需要提到的是,这个字段在计算区块散列的时候要清零.xdag程序默认使用dnet作为网络传输层.传输过程中的区块信息是加密的.使用作者的半对称算法和临时密钥对每个传输的块进行编码,并使用相同的密钥对另一侧进行解码.临时密钥由发送方生成,然后使用存储在文件dnet_key.dat中的发送方的私钥进行编码,然后使用发送方的公钥将其解码. 加密算法为长度为8192bits的RSA算法.

节点间不仅能传输区块,还能传输伪区块.伪区块是一些需要对方答复的请求.对于伪区块,字段0的类型必须是0,字段1的类型必须是消息类型.

伪区块的消息类型如下:

0 请求某个时间段内的所有区块信息.起始时间在区块头的时间字段中,结束时间在区块头的金额字段中.
1 对消息类型0的回复.这个回复必须在所有请求的区块之后.
2 请求某个时间段内的所有区块的汇总信息.起始时间在区块头的时间字段中,结束时间在区块头的金额字段中.
3 对消息类型2的回复.回复是一个区块,其中的后256个字节是由16个汇总结构组成.每个汇总将总的时间段划分成16等份.
每个汇总信息包括两个内容:
- 第一个64-bit(小端字节序),是该子区间中所有块的所有64-bit之和
- 第二个64-bit(小端字节序),是从这个子区间开始的所有块的长度之和.

每个请求在字段1里有自己的ID.每个回复必须在字段1里拥有相同的ID.每个伪区块消息在字段2,字段3以及字段4的开头存放统计结构

统计结构如下:

- 发送方的主链难度, 16个字节;
- 网络主链上已知的主链最大难度, 16字节;
- 发送方的有效区块个数, 8个字节;
- 网络中的最大的有效区块个数, 8个字节;
- 发送方的主块个数, 8个字节;
- 网络中的最大的主块个数, 8个字节;
- 发送方已知的节点个数, 4个字节;
- 网络中已知的节点个数, 4个字节;

伪区块中的其他字段填写发送方的节点地址信息.节点地址信息是6个字节,IP(4 字节, 大端字节序)和 端口(小端字节序)

## 翻译
本白皮书由reymondtu翻译并校对.(reymontu@gmx.com,XDAG:+09AAQmaOlLswDbHjHlJ+MFScwG+wfMB)
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -120,6 +120,20 @@ Then run below command

xdag> xfer [amount] [address]

Build (Mac Os):
-----------------------
- Install dependencies:

$ brew install openssl
$ ln -s /usr/local/opt/openssl/include/openssl /usr/local/include
$ ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/

- Make

$ cd xdag/client
$ make


Main chain idea:
---------------

Expand Down
24 changes: 20 additions & 4 deletions client/Makefile
Expand Up @@ -7,6 +7,17 @@ dfslib = $(dfstools)/dfslib
dar = ../dus/programs/dar/source
ldusinc = ../ldus/source/include/ldus
utils = ./utils
OS := $(shell uname)

ifeq ($(OS), Darwin)
asm_src = \
sha256-mb-x86_64-mac.s \
x86_64cpuid-mac.s
else
asm_src = \
sha256-mb-x86_64.s \
x86_64cpuid.s
endif

sources = \
address.c \
Expand All @@ -21,14 +32,12 @@ sources = \
miner.c \
mining_common.c \
sha256.c \
sha256-mb-x86_64.s \
storage.c \
sync.c \
transport.c \
wallet.c \
commands.c \
terminal.c \
x86_64cpuid.s \
$(dnet)/dnet_crypt.c \
$(dnet)/dnet_database.c \
$(dnet)/dnet_main.c \
Expand Down Expand Up @@ -103,13 +112,20 @@ headers = \
./json-rpc/rpc_wrapper.h \


flags = -std=gnu11 -O3 -DDFSTOOLS -DCHEATCOIN -DNDEBUG -g -lpthread -lcrypto -lssl -lm -Wall -Wmissing-prototypes -Wno-unused-result -Wl,--export-dynamic

ifeq ($(OS), Darwin)

flags = -std=gnu11 -O3 -DDFSTOOLS -DCHEATCOIN -DNDEBUG -g -lpthread -lcrypto -lssl -lm -Wall -Wmissing-prototypes -Wno-unused-result
else
flags = -std=gnu11 -O3 -DDFSTOOLS -DCHEATCOIN -DNDEBUG -g -lpthread -lcrypto -lssl -lm -Wall -Wmissing-prototypes -Wno-unused-result -Wl,--export-dynamic

endif


all: xdag

xdag: $(sources) $(headers) Makefile
gcc -o xdag $(sources) -DSHA256_USE_OPENSSL_TXFM -DSHA256_OPENSSL_MBLOCK -I$(SRCROOT) -I$(utils) $(flags)
gcc -o xdag $(sources) $(asm_src) -DSHA256_USE_OPENSSL_TXFM -DSHA256_OPENSSL_MBLOCK -I$(SRCROOT) -I$(utils) $(flags)

clean:
rm xdag
Expand Down
20 changes: 7 additions & 13 deletions client/address.c
Expand Up @@ -25,9 +25,9 @@ int xdag_address_init(void)
int xdag_address2hash(const char *address, xdag_hash_t hash)
{
uint8_t *fld = (uint8_t*)hash;
int i, c, d, e, n;
int i, c, d, n;

for (e = n = i = 0; i < 32; ++i) {
for (int e = n = i = 0; i < 32; ++i) {
do {
if (!(c = (uint8_t)*address++))
return -1;
Expand All @@ -51,25 +51,19 @@ int xdag_address2hash(const char *address, xdag_hash_t hash)
}

// converts hash to address
const char *xdag_hash2address(const xdag_hash_t hash)
void xdag_hash2address(const xdag_hash_t hash, char *address)
{
static char bufs[4][33];
static int k = 0;
char *buf = &bufs[k++ & 3][0], *ptr = buf;
int i, c, d;
int c, d;
const uint8_t *fld = (const uint8_t*)hash;

for (i = c = d = 0; i < 32; ++i) {
for (int i = c = d = 0; i < 32; ++i) {
if (d < 6) {
d += 8;
c <<= 8;
c |= *fld++;
}
d -= 6;
*ptr++ = bits2mime[c >> d & 0x3F];
*address++ = bits2mime[c >> d & 0x3F];
}

*ptr = 0;

return buf;
*address = 0;
}
2 changes: 1 addition & 1 deletion client/address.h
Expand Up @@ -12,6 +12,6 @@ extern int xdag_address_init(void);
extern int xdag_address2hash(const char *address, xdag_hash_t hash);

/* converts hash to address */
extern const char *xdag_hash2address(const xdag_hash_t hash);
extern void xdag_hash2address(const xdag_hash_t hash, char *address);

#endif
27 changes: 19 additions & 8 deletions client/block.c
Expand Up @@ -1359,6 +1359,7 @@ int xdag_print_block_info(xdag_hash_t hash, FILE *out)
{
struct tm tm;
char tbuf[64];
char address[33];
int i;

pthread_mutex_lock(&block_mutex);
Expand All @@ -1381,17 +1382,25 @@ int xdag_print_block_info(xdag_hash_t hash, FILE *out)
fprintf(out, " hash: %016llx%016llx%016llx%016llx\n",
(unsigned long long)h[3], (unsigned long long)h[2], (unsigned long long)h[1], (unsigned long long)h[0]);
fprintf(out, "difficulty: %llx%016llx\n", xdag_diff_args(bi->difficulty));
fprintf(out, " balance: %s %10u.%09u\n", xdag_hash2address(h), pramount(bi->amount));
xdag_hash2address(h, address);
fprintf(out, " balance: %s %10u.%09u\n", address, pramount(bi->amount));
fprintf(out, "-------------------------------------------------------------------------------------------\n");
fprintf(out, " block as transaction: details\n");
fprintf(out, " direction address amount\n");
fprintf(out, "-------------------------------------------------------------------------------------------\n");
fprintf(out, " fee: %s %10u.%09u\n", (bi->ref ? xdag_hash2address(bi->ref->hash) : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
if(bi->ref) {
xdag_hash2address(bi->ref->hash, address);
}
else {
strcpy(address, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}
fprintf(out, " fee: %s %10u.%09u\n", address,
pramount(bi->fee));

for (i = 0; i < bi->nlinks; ++i) {
xdag_hash2address(bi->link[i]->hash, address);
fprintf(out, " %6s: %s %10u.%09u\n", (1 << i & bi->in_mask ? " input" : "output"),
xdag_hash2address(bi->link[i]->hash), pramount(bi->linkamount[i]));
address, pramount(bi->linkamount[i]));
}

fprintf(out, "-------------------------------------------------------------------------------------------\n");
Expand All @@ -1400,7 +1409,8 @@ int xdag_print_block_info(xdag_hash_t hash, FILE *out)
fprintf(out, "-------------------------------------------------------------------------------------------\n");

if (bi->flags & BI_MAIN) {
fprintf(out, " earning: %s %10u.%09u %s.%03d\n", xdag_hash2address(h),
xdag_hash2address(h, address);
fprintf(out, " earning: %s %10u.%09u %s.%03d\n", address,
pramount(MAIN_START_AMOUNT >> ((MAIN_TIME(bi->time) - MAIN_TIME(XDAG_ERA)) >> MAIN_BIG_PERIOD_LOG)),
tbuf, (int)((bi->time & 0x3ff) * 1000) >> 10);
}
Expand Down Expand Up @@ -1445,13 +1455,14 @@ int xdag_print_block_info(xdag_hash_t hash, FILE *out)
struct block_internal *ri = ba[i];
if (ri->flags & BI_APPLIED) {
for (int j = 0; j < ri->nlinks; j++) {
if (ri->link[j] == bi && ri->linkamount[j]) {
if(ri->link[j] == bi && ri->linkamount[j]) {
t = ri->time >> 10;
localtime_r(&t, &tm);
strftime(tbuf, 64, "%Y-%m-%d %H:%M:%S", &tm);
xdag_hash2address(ri->hash, address);
fprintf(out, " %6s: %s %10u.%09u %s.%03d\n",
(1 << j & ri->in_mask ? "output" : " input"), xdag_hash2address(ri->hash),
pramount(ri->linkamount[j]), tbuf, (int)((ri->time & 0x3ff) * 1000) >> 10);
(1 << j & ri->in_mask ? "output" : " input"), address,
pramount(ri->linkamount[j]), tbuf, (int)((ri->time & 0x3ff) * 1000) >> 10);
}
}
}
Expand All @@ -1469,7 +1480,7 @@ int xdagGetLastMainBlocks(int count, char** addressArray)
int i = 0;
for (struct block_internal *b = top_main_chain; b && i < count; b = b->link[b->max_diff_link]) {
if (b->flags & BI_MAIN) {
strcpy(addressArray[i], xdag_hash2address(b->hash));
xdag_hash2address(b->hash, addressArray[i]);
++i;
}
}
Expand Down

0 comments on commit e3b0791

Please sign in to comment.