Декодирование входных данных транзакции с помощью web3j (Java)

Мой вариант использования следующий: я хотел бы, чтобы демон следил за тем, как пользователи взаимодействуют с моим смарт-контрактом. Как я это вижу, я смотрю на входящие блоки и пытаюсь декодировать входные данные с адресом to, соответствующим моему контракту. Мне не удалось найти в web3J способ декодирования данных.

1- Есть ли способ декодировать данные с помощью web3J?

2- Есть ли у меня другой способ достичь своей цели, кроме декодирования входных данных? События кажутся мне трудным выбором, так как я не смогу легко следить за всеми вещами. И эти методы не могут применяться к смарт-контрактам, которыми я не владею.

Спасибо за помощь.

Предложение для JS уже существует abi-decoder answer . Один из вариантов — создание сканера на JS, который регулярно отправляет данные.
Здесь также уже было сделано предложение для web3j . Однако это не помогает с совместимостью с библиотекой.

Ответы (4)

Я думаю, что-то вроде первого вопроса. Если вы посмотрите, что такое транзакция, для узла это просто большая длинная строка байтов. Если байты можно преобразовать в ASCII, вы можете использовать метод

web3.toAscii()

Это может дать или не дать вам что-то. Например, вот tx a, который я сделал на Ropsten, где вы получаете обратно некоторые читаемые входные данные и некоторые нечитаемые данные: https://ropsten.etherscan.io/tx/0xe4058b8f612f20600d8aae1230d93b7b5c63398ddde0a3a6aed236659f425c0e (просто нажмите вход Convert to Ascii внизу )

Тем не менее, лучший (самый простой) способ сделать это — владеть децентрализованным приложением. Поэтому, когда они заполняют форму, вы просто сохраняете вводимые данные. Следующим лучшим, как вы сказали, является использование событий. Они раздражают, но у вас может быть только одно длинное событие в начале ваших контрактов:

    contract Test {
       event Input(string desc, address _party, uint _input1, string _input2);  

     function somefunc(uint _input1, string _input2) returns(bool success){
        Input("Input",msg.sender,_input1,_input2);
      return true;
   }
}

Но тогда для чужих контрактов вам не повезло, так как у вас нет этого события.

Спасибо вам за ответ. Я только что добавил новую проблему на web3j github для реализации такой возможности. Глядя на код, несложно перепроектировать некоторые функции и декодировать строку. Кодируется функция <name> , значение параметров.
Потрясающе, отличная вещь, которую нужно знать. Похоже, вы будете в порядке, пытаясь декодировать его, если контракт не пытается намеренно скрыть входные данные.
Даже в этом случае я не слишком возражаю. Я извлеку ввод и предложу ввод пользователям, поскольку у них может быть право доступа к нему, которого нет у моего серверного приложения.
    ERC20 javaToken = ERC20.load(contractAddress, web3, creds, new DefaultGasProvider());
    System.out.println("ALL HISTORY OF TT");
    javaToken.transferEventFlowable(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST)
     .subscribe(event
     -> System.out.println("from: " + event._from + ", to: " + event._to + ", value: " + event._value));    

Я думаю, это поможет вам

Логика, которую я использовал, выглядит следующим образом:

web3j.transactionflowable.subscribe(tx -> {

checkIfMyTransaction(tx.getTo, tx.getHash);

});

public void checkIfMyTransaction(String toAddress, String txHash){

// check data base if the address belong to my application and then following logic. This can be contract address or wallet address. 

// if contract address:

EthTransaction ethTransaction=web3j.getTransactionByHash(txHash).send;
Transaction transaction=ethTransaction.getTransaction.get();
transaction.getFrom;
transaction.getBlockNumer;

// Take all info like blocknumber, blockhash etc from above call. For input data, we create new method. 

decodeInput(transaction.getInput);
}

public void decodeInput(String data) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    String inputData = data;
    String method = inputData.substring(0,10);
    log.info("Method >>>>>> " +method);
    String to = inputData.substring(10,74);
    String value = inputData.substring(74);
    Method refMethod = TypeDecoder.class.getDeclaredMethod("decode",String.class,int.class,Class.class);
    refMethod.setAccessible(true);
    Address address = (Address)refMethod.invoke(null,to,0,Address.class);
    log.info("Address>>>>>> " +address.toString());
    Uint256 amount = (Uint256) refMethod.invoke(null,value,0,Uint256.class);
    log.info("amount >>>>>> " +amount);
}

У меня было такое же требование, и я начал взламывать его в генераторе контрактов web3j. Из-за (ИМХО) чрезмерно сложного подхода я отказался от этого и вместо этого написал для этого свою собственную автономную библиотеку Java. Вам вообще не нужен web3j, вам понадобится только ABI контракта в формате JSON.

https://github.com/rvullriede/evm-аби-декодер

Пример использования:

// Abi can be found here: https://etherscan.io/address/0x7a250d5630b4cf539739df2c5dacb4c659f2488d#code
AbiDecoder uniswapv2Abi=new AbiDecoder(pathToAbiJsonFile).getFile());

// tx: https://etherscan.io/tx/0xde2b61c91842494ac208e25a2a64d99997c382f6aaf0719d6a719b5cff1f8a07
String inputData="0x18cbafe5000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000165284993ac4ac00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000d4cf8e47beac55b42ae58991785fa326d9384bd10000000000000000000000000000000000000000000000000000000062e8d8510000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";

/**
 * #  Name          Type       Data
 * ----------------------------------------------------------------------
 * 0  amountIn      uint256    10000000
 * 1  amountOutMin  uint256    6283178947560620
 * 2  path          address[]  0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
 *                             0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
 * 3  to            address    0xD4CF8e47BeAC55b42Ae58991785Fa326d9384Bd1
 * 4  deadline      uint256    1659426897
 */

DecodedFunctionCall decodedFunctionCall=uniswapv2Abi.decodeFunctionCall(inputData);

System.out.println(decodedFunctionCall.getName()); // prints swapExactTokensForETH

Это все еще молодой проект, если у вас возникнут проблемы (например, с конкретными контрактами), сообщите мне об этом через средство отслеживания проблем проекта github.

Надеюсь, это поможет!

Не копируйте и не вставляйте один и тот же ответ несколько раз. Они будут помечены как спам.
Спасибо за подсказку! Я просто пытался помочь и по другому вопросу. Вместо этого я дам ссылку на эту тему.