Skip to content
This repository was archived by the owner on Sep 13, 2022. It is now read-only.

Commit 81421c8

Browse files
committed
best practice in using bigint data type for blockchain industry
1 parent 0b35800 commit 81421c8

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

zh/_index.md

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ summary: 为开发者提供 TiDB 中文版开发指南。
7777
- [分页的最佳实践](tidb-database-development-specification/best-practices-for-paging.md)
7878
- [唯一序列号生成方案](tidb-database-development-specification/unique-serial-number-generation-scheme.md)
7979
- [流程规范](tidb-database-development-specification/process-specification.md)
80+
- [TiDB 区块链大整数最佳实践](tidb-database-development-specification/best-practice-in-using-bigint-data-type-for-blockchain-industry.md)
8081

8182
</NavColumn>
8283

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: TiDB 区块链大整数最佳实践
3+
summary: 介绍 区块链大整数 在 TiDB 中的应用
4+
---
5+
6+
# TiDB 区块链大整数最佳实践
7+
8+
## 区块链大整数
9+
10+
现在大部分程序语言直接支持 64 bit 的内置类型,即直接支持相关运算。而超过 64 bit 的的整数,需要自己来实现。
11+
大整数是 区块链 的很重要的组成部分。比如用大整数来标识基础数据类型,如 账号、地址、交易 hash、区块 hash;比如有许多大整数计算的算法,比如 merkerl,pow 等。 所以区块链应用场景,一般来说,大整数支持是必须的。
12+
13+
## TiDB 大整数 解决方案
14+
15+
TiDB 没有直接支持大整数的存储与计算(默认支持的最大整数是 `64bit`),针对 大整数 比较通用的解决方案是:
16+
17+
-`binary(M)` 来存储大整数 —— `M` 表示大整数的字节数(比如,`U256``binary(32)` 来表示)。
18+
- **必须** 高位补 0,保证 M 个字节全部填满。
19+
- **必须**`big-endian` 字节序列—— 这个由应用保证,生成的字节序列是 `big-endian` 的。
20+
具体实现细节、原理请看下文。
21+
22+
## 大整数在 TiDB 实现原理
23+
24+
### 1. 存储
25+
26+
TiDB 默认支持的最大整数类型是 64bit,所以跟大多数程序语言一样,是默认不支持大整数的。
27+
但是,TiDB 是数据库,如果仅仅存储这类大整数数据,还是没问题的。
28+
在 TiDB 用 `binary(M)` 来存储大整数。其中,M 是根据 大整数 `bit 数` 除以 8 得到。
29+
30+
> 一般情况下,大整数 `U/S + bit`位数一起来表示类型。其中,`U`表示无符号整数;`S`表示有符号整数。所以,U256 即表示 无符号的 256bit 的整数。当然,还可以有 有符号 128bit 整数 -\> S128。当然,计算机直接支持的,u64 表示 64bit 的无符号整数。
31+
32+
> `binary(M)``M` 表示字节数。所以,如果用 `binary(M)` 来表示 `U256`,那么就需要 32字节`(32=256/8)` =\> `binary(32)` 来存储 `U256`/`S256`
33+
34+
### 2. 字节序(Byte Order)
35+
36+
字节序,大家应该都有了解。或者,网上资料、说明一大坨,自己看吧。
37+
38+
简单来说,0x03020100 需要 4字节存储,假设从位置 p 开始
39+
40+
```C++
41+
// 存储中存放示例
42+
// big-enian
43+
p[0] = 0x03;
44+
p[1] = 0x02;
45+
p[2] = 0x01;
46+
p[3] = 0x00; // 大(高位)存储 放在了 小数据(低位数据)。
47+
// little-endian
48+
p[0] = 0x00;
49+
p[1] = 0x01;
50+
p[2] = 0x02;
51+
p[3] = 0x03; // 大(高位)存储 放在了 大数据(高位数据)。
52+
```
53+
54+
所以,很明显的,排序还跟 ByteOrder 相关。一般系统的默认 ByteOrder ,指的是系统内置类型整数的存储到 byte 中的顺序。而大整数,是我们自己实现的。
55+
56+
而系统默认排序算法,一般都是从 bytes 的低字节开始到最后一个字节,一个个遍历比较。
57+
> binary 本质上来说也是 bytes,所以排序规则也是 从 `低字节(byte[0])``高字节(byte[len-1])` 一个个字节进行比较。
58+
>
59+
> 我们知道,整数中,高位数据肯定比低位数据大(比如 `百位的 1``十位 的任何数字`都大)。所以正常的整数比较,都是高位数据跟高位数据比较 —— 这就要求 binary 存储数据,`高位数据` 存储在 `低位存储`,从上面示例可以知道,这是 `big-endian`!!!
60+
61+
### 3. 排序
62+
63+
我们已经知道,binary 必须要以 big-endian 存储。但是,这里还有一个注意点:不会比较长度。具体看如下例子:
64+
> A = 0x0203
65+
> B = 0x010203
66+
> 如果作为整数比较,那么 `0x0203 < 0x010203` 得到 `A < B`
67+
> 但是,如果 binary 比较,那么会先比较最高位字节即 `0x02 > 0x01` ,所以 `A > B`
68+
> 附注:如果最高位字节相等,那么比较下一个 字节;如此反复;
69+
70+
所以,我们期望的是用 binary 比较 有 正数比较 相同的效果。其实,这里面最重要的点是没比较长度——既然它不比较,那么我们就弄成长度相等(高位补0),那就不需要比较长度了!!!
71+
72+
其实,我们一般的程序语言内置类型(比如 u64),本质上来说就是 高位补0 了,所以即等长比较大小的。
73+
74+
> OK,用了定长数据,继续上面的例子,来看看效果:
75+
> 我们假设都是 4字节整数(u32)
76+
> A = `0x0000 0203`
77+
> B = `0x0001 0203`
78+
> 所以根据刚刚算法,`0x00 == 0x00` , 然后 `0x00 < 0x01` ,得到 `A < B` ,符合预期!!!。
79+
80+
### 4. 小结
81+
82+
所以,这里 TiDB 来处理大整数,两个基本的问题都解决了:
83+
84+
- 存储: binary(M) 来存储,M 可以根据大整数 bit数 来计算 。
85+
- 字节序: 必须要以 big-endian 生成的 bytes ,来存储到 binary 中。
86+
- 注意,这个也是 应用来保证的。只有以这种方式存储,才能得到满足预期的结果
87+
- 排序: 通过补0 来保证存储的 binary 长度一致,所以 binary 默认排序可以满足。
88+
- 注意,这里的补0不是字符串 `'0'(0x30)` ,而是数值`0(0x00)`; 而之前的示例都是用 hex 表示,即整数数据,而非字符串 -- **切记切记**
89+
- 有了排序,存储的时候就可以按序存储,查询的时候,也可以高效的利用索引,而且查询的数据也会符合预期。
90+
- 展示: 一般情况下,binary 一般是用 hex 格式展示
91+
- 如果是 非打印字符,那么一般默认用 hex 展示。
92+
- 我们这里的二进制数据,所以是没法打印的,所以只能用 hex
93+
- 其它: 其它的种种 大整数功能,请应用程序来实现
94+
- 其它功能,包括但不限于: 基本的整数运算,安全(溢出)等等。
95+
96+
## 大整数 在应用程序实现
97+
98+
一般情况下,高级程序语言本身库来支持 大整数,而且支持一整套运算。
99+
100+
> 比如, Golang 有 `big.Int` (系统库);C/C++ 有 `gmp` ; Java 有 `BigInteger` 等。
101+
102+
- 基本功能: 应用端都是没问题的。
103+
- 安全: 溢出等安全问题,一般 整数运算 类似,要注意。
104+
- 存储: 要注意在转换的时候,要补0 来达到 特定字节数的 bytes。
105+
- 字节序: 一定要是 big-endian (不过一般默认都是该字节序)。

0 commit comments

Comments
 (0)