编码
在TRON
中使用到的其中二种编码:
- base58check
- hex
- byte
为什么说这三种编码,主要是这三种比较常用。
首先用到最多的就是地方就是基于byte[]
衍生的各种编码场景如:
- 私钥
- protobuf
- leveldb存储
都是先基于byte
数据来的,其它区块链当中也有大量使用byte
。
byte
使用场景:
- 数据存储
- 网络传输
这个比较在常用,在tron链中,越是底层的数据存储越是需要二进制,如私钥、数据存储等,就是byte[]
这种格式。
使用protobuf序列化也是byte[],leveldb 的存储也是基于byte[]。
可以理解为,最重要和核心的数据形式。但是byte也有一个问题,就是表现形式上,太长了,不利于人类的阅读体验。
数据之间需要进行转换才能使用,首先,数据存储到leveldb中,是只能存储二进制数据,也就是在源头上,数据就必须是二进制形式存在的,如果要使用转换数据是必然的行为。
当然你说我就要二进制,就不嫌麻烦,整套系统都用二进制操作,也不是不可以,效率是少了一步转换肯定是可以,但是内存上有没有那么大的空间。二是我调试时,看二进制没问题,完全不在话下,就要看二进制,那随意
看看在内存中的表现形式,这种的表现形式,更长,更难以理解,但是leveldb在存储二进制时,还会使用到一种叫varint的压缩算法,protobuf中也有使用,这种编码后面有机会专门说一下。
IDEA将二进制
自动转成了十进制
的表现形式,这个就不赘述了。
所以一句话,这是在tron中最基础的数据形式,为啥这么点事,我要写这么多字,因为有很多社区开发者在这一块有很多问题,总是搞混应用场景,总结来说可以简单的理解两个应用场景:
- 数据存储是二进制
- 网络传输是二进制
base58check
base58check是基于base58的基础上加了一个校验码。 在二进制数据的传输过程中,为了防止数据传输的错误,保护数据安全,通常会加一个校验码。通过校验码的配合可以发现数据是否被破坏或者是否在发送时输入错误了。Base58Check就是Base58加上校验码,或者可以说是Base58的一种编码形式,在比特币系统中生成钱包地址的时候就使用到了这种编码形式,TRON中的地址也是使用到了这种编码。
使用场景:
- 钱包地址
- 转账
- 配置文件
为什么使用base58编码? 因为是给人类看的。
什么是base58check? 就是在 base64的基础上去掉了6个容易混淆的字母、字符,只剩58个了,所以叫:base58。
代码语言:javascript复制123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
哪几个符号? 不含Base64中的0(数字0)、O(大写字母o)、l(小写字母 L)、I(大写字母i),以及“ ”和“/”两个字符。 简而言之,Base58就是由不包括(0,O,l,I, ,/)的大小写字母和数字组成。
check是指什么意思? 为了增加防止打印和转录错误的安全性,比特币常用的是Base58Check,它是一种内置错误校验代码的Base58编码格式。检验和是额外4个字节,被添加到正在编码的数据末端。校验和是从编码的数据的哈希值中得到的,所以可以用来检测并避免转录和输入中产生的错误。
使用Base58check编码时,解码软件会计算数据的校验和并和编码中自带的校验和进行对比。二者不匹配则表明有错误产生,这个Base58Check的数据就是无效的。这就防止输错的比特币地址被钱包软件认为是有效的地址,造成资金的丢失。
到底长啥样?长这样:
TNNqZuYhMfQvooC4kJwTsMJEQVU3vWGa5u
怎么用?
使用上,需要把base58check字符串,转成二进制byte[],毕竟人看完了,机器也得看。
hex 十六进制
应用场景:
- 程序内部表示地址,不是给人看的
- 表示hash字符串
地址有两种表示形式,一是base58check,二是hex形式,第一种是给人看的,第二种程序内部使用。这两种编码形式可以互相转换。本质是代表的是一个数种,多种表现形多。仅仅是使用的对象不同而已。
长什么样子? 最多的场景是使用Hash表示的地方,都可以用十六进制表示,比二进制要表示要简短不止一点点。
代码中的应用
地址有两种编码格式,下面的hexAddress就是十六进制。
代码语言:javascript复制{
"address": "TJfTWgzey3d3QHbrautjRmANNULfk91VFj",
"hexAddress": "415f5dc2006f98936ca054ea49b4d38d292c9429c8"
}
Bash58Check 测试
代码语言:javascript复制package org.tron.walletserver;
import org.tron.common.crypto.Sha256Sm3Hash;
import org.tron.common.utils.Base58;
import java.util.Arrays;
/**
* @author liukai
* @since 2022/03/02.
*/
public class Base58CheckTest {
private static byte[] decode58Check(String input) {
byte[] decodeCheck = Base58.decode(input);
if (decodeCheck.length <= 4) {
return null;
}
byte[] decodeData = new byte[decodeCheck.length - 4];
System.arraycopy(decodeCheck, 0, decodeData, 0, decodeData.length);
byte[] hash0 = Sha256Sm3Hash.hash(decodeData);
byte[] hash1 = Sha256Sm3Hash.hash(hash0);
if (hash1[0] == decodeCheck[decodeData.length]
&& hash1[1] == decodeCheck[decodeData.length 1]
&& hash1[2] == decodeCheck[decodeData.length 2]
&& hash1[3] == decodeCheck[decodeData.length 3]) {
return decodeData;
}
return null;
}
public static void main(String[] args) {
String bash58CheckStr = "TJfTWgzey3d3QHbrautjRmANNULfk91VFj";
byte[] bytes = decode58Check(bash58CheckStr);
System.out.println("---------");
System.out.println(Arrays.toString(bytes));
System.out.println("---------");
}
}
结果:
--------- [65, 95, 93, -62, 0, 111, -104, -109, 108, -96, 84, -22, 73, -76, -45, -115, 41, 44, -108, 41, -56] ---------
总结
二进制、十六进制、base58check 这几种数据格式和编码都是在区块链在很常用的一套数据结构和编码,其实很多都是互相借鉴,谁也别说抄谁。 总的来说,了解了一个套路,再看其他的链就大同小异了。