• Web3j 继承StaticStruct的类所有属性必须为Public <DynamicArray<StaticStruct>>


    Web3j 继承StaticStruct的类所有属性必须为Public,属性的顺序和数量必须和solidity 里面的struct 属性相同,否则属性少了或者多了的时候会出现错位

    Web3j 继承StaticStruct的类所有属性不能为private,因为web3j 是通过长度去截取返回值解析成对应的属性进行赋值的。要获取一个list对象时,web3j是按一个类的所有public属性个数去截取总长度的,再进行解析赋值到没一个属性里

    StaticStruct类

    1. import lombok.Data;
    2. import org.web3j.abi.datatypes.Address;
    3. import org.web3j.abi.datatypes.StaticStruct;
    4. import org.web3j.abi.datatypes.Type;
    5. import org.web3j.abi.datatypes.generated.Uint256;
    6. @Data
    7. public class ChildStaticStruct extends StaticStruct {
    8. public Uint256 attr1;
    9. public Uint256 attr2;
    10. public Address attr3;
    11. public ChildStaticStruct(Uint256 attr1, Uint256 attr2, Address attr3) {
    12. super(new Type[]{attr1,attr2,attr3});
    13. }
    14. }
    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import org.web3j.abi.FunctionEncoder;
    4. import org.web3j.abi.FunctionReturnDecoder;
    5. import org.web3j.abi.TypeReference;
    6. import org.web3j.abi.datatypes.Address;
    7. import org.web3j.abi.datatypes.DynamicArray;
    8. import org.web3j.abi.datatypes.Function;
    9. import org.web3j.abi.datatypes.Type;
    10. import org.web3j.protocol.Web3j;
    11. import org.web3j.protocol.core.DefaultBlockParameterName;
    12. import org.web3j.protocol.core.methods.request.Transaction;
    13. import org.web3j.protocol.core.methods.response.EthCall;
    14. import java.io.IOException;
    15. import java.util.Arrays;
    16. import java.util.List;
    17. public class TestContract {
    18. private static final Logger logger = LoggerFactory.getLogger(TestContract.class);
    19. private String address;
    20. private Web3j web3j;
    21. public TestContract(String address, Web3j web3j) {
    22. this.address = address;
    23. this.web3j = web3j;
    24. }
    25. public List<ChildStaticStruct> getStaticStructList(String address) throws IOException {
    26. List<Type> inputParameters = Arrays.asList( new Address(address));
    27. List<TypeReference<?>> outputParameters = Arrays.asList(new TypeReference>(){});
    28. Function function = new Function("getStaticStructList",inputParameters,outputParameters);
    29. Transaction transaction = Transaction.createEthCallTransaction(null,address, FunctionEncoder.encode(function));
    30. EthCall response = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
    31. List<Type> output = FunctionReturnDecoder.decode(response.getValue(),function.getOutputParameters());
    32. List<ChildStaticStruct> results = (List<ChildStaticStruct>)output.get(0).getValue();
    33. return results;
    34. }
    35. }

    web3j的TypeDecoder 里的decodeArrayElements 验证了是否为StructType子类,

    在currOffset += getSingleElementLength(input, currOffset, cls) * 64)判断了截取的长度

    1. if (StructType.class.isAssignableFrom(cls)) {
    2. elements = new ArrayList(length);
    3. currOffset = 0;
    4. for(currOffset = offset; currOffset < length; currOffset += getSingleElementLength(input, currOffset, cls) * 64) {
    5. if (DynamicStruct.class.isAssignableFrom(cls)) {
    6. value = decodeDynamicStruct(input, offset + DefaultFunctionReturnDecoder.getDataOffset(input, currOffset, typeReference), TypeReference.create(cls));
    7. } else {
    8. value = decodeStaticStruct(input, currOffset, TypeReference.create(cls));
    9. }
    10. elements.add(value);
    11. ++currOffset;
    12. }
    13. String typeName = Utils.getSimpleTypeName(cls);
    14. return (Type)consumer.apply(elements, typeName);
    15. }

    getSingleElementLength 验证了截取长度是根据public属性数量去截取Utils.staticStructNestedPublicFieldsFlatList(type).size(),pirvate计算长度

    1. static <T extends Type> int getSingleElementLength(String input, int offset, Class<T> type) {
    2. if (input.length() == offset) {
    3. return 0;
    4. } else if (!DynamicBytes.class.isAssignableFrom(type) && !Utf8String.class.isAssignableFrom(type)) {
    5. return StaticStruct.class.isAssignableFrom(type) ? Utils.staticStructNestedPublicFieldsFlatList(type).size() : 1;
    6. } else {
    7. return decodeUintAsInt(input, offset) / 32 + 2;
    8. }
    9. }

     staticStructNestedPublicFieldsFlatList方面里面通过Modifier.isPublic(field.getModifiers())过滤了public  

    1. public static List staticStructNestedPublicFieldsFlatList(Class classType) {
    2. return (List)staticStructsNestedFieldsFlatList(classType).stream().filter((field) -> {
    3. return Modifier.isPublic(field.getModifiers());
    4. }).collect(Collectors.toList());
    5. }

    Modifier 里面比较了Public

    1. public static boolean isPublic(int mod) {
    2. return (mod & PUBLIC) != 0;
    3. }

  • 相关阅读:
    UE4 使用材质后期 制作玻璃有雨效果
    C++制作游戏引擎之一 方向键控制地球上下左右乱跑
    JAVA地铁舆情管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
    小芯片chiplet技术杂谈
    微信核酸检测预约小程序系统毕业设计毕设(4)开题报告
    微服务组件--限流框架Spring Cloud Hystrix分析
    【LeetCode-中等题】40. 组合总和 II
    彻底了解线程池的原理——40行从零开始自己写线程池
    【MySQL索引学习】MySQL索引详细学习
    国内跨网数据传输有哪些难题,该如何解决?
  • 原文地址:https://blog.csdn.net/music0ant/article/details/132646999