长安链EVM合约地址与数据库存储账户的关系及计算

古城微笑少年丶 2024-05-08 07:15 100阅读 0赞

长安链EVM地址说明

ChainMaker目前已支持的证书模型与以太坊的公钥模型不相同,为此ChainMaker在SDK中支持通过证书的SKI字段转换为EVM中所支持的地址格式。

以下为样例证书信息部分内容:

  1. Certificate:
  2. Data:
  3. Version: 3 (0x2)
  4. Serial Number: 775620 (0xbd5c4)
  5. Signature Algorithm: ecdsa-with-SHA256
  6. Issuer: C=CN, ST=Beijing, L=Beijing, O=wx-org1.chainmaker.org, OU=root-cert, CN=ca.wx-org1.chainmaker.org
  7. Validity
  8. Not Before: Apr 30 07:04:20 2021 GMT
  9. Not After : Apr 29 07:04:20 2026 GMT
  10. Subject: C=CN, ST=Beijing, L=Beijing, O=wx-org1.chainmaker.org, OU=admin, CN=admin1.sign.wx-org1.chainmaker.org
  11. Subject Public Key Info:
  12. Public Key Algorithm: id-ecPublicKey
  13. Public-Key: (256 bit)
  14. pub:
  15. 04:05:63:4d:46:6f:b0:3e:30:cb:4f:b3:12:93:da:
  16. 10:1e:d4:50:ea:36:ac:3f:85:e4:3b:c3:a8:7e:ff:
  17. 4a:57:7d:f1:55:b7:21:0d:94:2f:9a:be:92:5b:dc:
  18. 90:a2:36:75:82:6e:8c:35:55:ff:f2:96:30:e2:f4:
  19. cc:cf:b7:75:5d
  20. ASN1 OID: prime256v1
  21. NIST CURVE: P-256
  22. X509v3 extensions:
  23. X509v3 Key Usage: critical
  24. Digital Signature, Key Encipherment, Certificate Sign, CRL Sign
  25. X509v3 Extended Key Usage:
  26. Any Extended Key Usage
  27. // 地址由SKI(Subject Key Identifier)值HASH生成(不包括':'符号)
  28. X509v3 Subject Key Identifier: 08:E6:25:3A:8B:F0:2B:BB:ED:03:34:71:B4:24:D0:A5:F1:C4:02:CC:B6:44:6E:42:30:AB:51:76:3A:34:C3:7B

查看证书信息的命令:

  1. openssl x509 -in consensus1.sign.crt -noout -text

http://t.csdn.cn/ACLUY

在ChainMaker Evm中,地址的生成参见以下流程:

1、SDK调合约方法,传入SKI

  1. //调用blanceOf函数,查询指定用户余额。
  2. //某用户SKI信息
  3. const client1AddrSki = "08E6253A8BF02BBBED033471B424D0A5F1C402CCB6446E4230AB51763A34C37B"
  4. func testUserContractTokenEVMBalanceOf(t *testing.T, client *ChainClient, address string, withSyncResult bool) {
  5. abiJson, err := ioutil.ReadFile(tokenABIPath)
  6. require.Nil(t, err)
  7. myAbi, err := abi.JSON(strings.NewReader(string(abiJson)))
  8. require.Nil(t, err)
  9. //通过SKI生成address
  10. addrInt, err := evmutils.MakeAddressFromHex(client1AddrSki)
  11. addr := evmutils.BigToAddress(addrInt)
  12. //指定合约方法
  13. methodName := "balanceOf"
  14. dataByte, err := myAbi.Pack(methodName, addr)
  15. require.Nil(t, err)
  16. data := hex.EncodeToString(dataByte)
  17. method := data[0:8]
  18. pairs := map[string]string{
  19. "data": data,
  20. }
  21. //调用合约
  22. result, err := invokeUserContractWithResult(client, tokenContractName, method, "", pairs, withSyncResult)
  23. require.Nil(t, err)
  24. balance, err := myAbi.Unpack(methodName, result)
  25. require.Nil(t, err)
  26. fmt.Printf("addr [%s] => %d\n", address, balance)
  27. }

2、对其HASH(Keccak256)并截取,生成address

  1. unc MakeAddressFromHex(str string) (*Int, error) {
  2. data, err := hex.DecodeString(str)
  3. if err != nil {
  4. return nil, err
  5. }
  6. return MakeAddress(data), nil
  7. }
  8. func MakeAddressFromString(str string) (*Int, error) {
  9. return MakeAddress([]byte(str)), nil
  10. }
  11. //将SKI进行HASH并截取。
  12. func MakeAddress(data []byte) *Int {
  13. address := Keccak256(data)
  14. addr := hex.EncodeToString(address)[24:]
  15. return FromHexString(addr)
  16. }
  17. func BigToAddress(b *Int) Address { return BytesToAddress(b.Bytes()) }

JAVA代码生成合约地址

通过集成长安链java-sdk,其中有CryptoUtils的工具类可以直接调用生成合约地址。

  1. String address = CryptoUtils.makeAddrFromCert(adminUser.getCertificate());

长安链数据存储DB的账户

通过mysql或者leveldb查看state_db数据库中的数据,会发现key值不是我们期望的address。那么状态数据库存的key又是什么呢?

可以先看一下,我的这篇文章:

http://t.csdn.cn/ACLUYicon-default.png?t=M7J4http://t.csdn.cn/ACLUY

我们调用Solidity使用的address在最终存储的时候,是按照EVM智能合约的存储方式去存的,而负责存储的对象为mapping,比如:

  1. mapping (address => uint256) public balanceOf;

state_db数据库中保存的KEY实际就是EVM处理后的存储HASH值。

evm账户存储值计算

  1. @Test
  2. void addressToAccountTest(){
  3. try {
  4. String certAddress = "0xb7414ecf2feeb4e1470f1f8ca57638ba3f272dc0";
  5. String storeAddress = new Address(256, certAddress).toString().substring(2);
  6. String slot = new Address(256, "3").toString().substring(2);
  7. byte[] addressData = Hex.decode(storeAddress + slot);
  8. Keccak.DigestKeccak keccak = new Keccak.Digest256();
  9. keccak.update(addressData, 0, addressData.length);
  10. byte[] accountAddress = keccak.digest();
  11. String account = Hex.toHexString(accountAddress);
  12. System.out.println(account);
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }
  16. }

想了解为什么这样计算,还是先掌握前边的链接文章。

发表评论

表情:
评论列表 (有 0 条评论,100人围观)

还没有评论,来说两句吧...

相关阅读