Decodificación de datos de entrada de transacciones con web3j (Java)

Mi caso de uso es el siguiente: me gustaría tener un demonio que supervise cómo los usuarios interactúan con mi contrato inteligente. La forma en que lo veo es mirar los bloques entrantes e intentar decodificar los datos de entrada con una dirección correspondiente a mi contrato. No pude encontrar en web3J una forma de decodificar datos.

1- ¿Hay alguna forma con web3J de decodificar los datos?

2- ¿Tengo alguna otra forma de lograr mi objetivo que no sea decodificar los datos de entrada? Los eventos me parecen una elección difícil ya que no podré monitorear fácilmente todas las cosas. Y estos métodos no pueden aplicarse a un contrato inteligente que no poseo.

Gracias por la ayuda.

Ya existe una propuesta para JS abi-decoder answer . Hacer un rastreador en JS que envíe datos regularmente es una opción.
También se hizo una sugerencia para web3j aquí . Sin embargo, no ayuda con la compatibilidad con la biblioteca.

Respuestas (4)

Supongo que algo así como la primera pregunta. Si observa qué es una transacción, para un nodo es solo una cadena de bytes grande y larga. Si los bytes son convertibles a ASCII, puede usar el

web3.toAscii()

Eso puede o no darte algo. Por ejemplo, aquí hay un tx que hice en Ropsten donde obtiene algunos datos de entrada legibles y algunos datos no legibles: https://ropsten.etherscan.io/tx/0xe4058b8f612f20600d8aae1230d93b7b5c63398ddde0a3a6aed236659f425c0e (simplemente haga clic en la entrada Convertir a Ascii en la parte inferior )

Dicho esto, la mejor manera (la más fácil) de hacer esto es tener el dapp. Entonces, cuando completan un formulario, solo guarda los datos de entrada. Lo siguiente mejor, como dijiste, es usar Eventos. Son molestos, pero podría tener solo un evento largo al comienzo de sus contratos:

    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;
   }
}

Pero luego, para los contratos de otras personas, no tiene suerte ya que no tiene este evento.

Gracias por la respuesta. Acabo de agregar un nuevo problema en web3j github para implementar tal posibilidad. Mirando el código, no parece demasiado difícil aplicar ingeniería inversa a algunas funciones y decodificar la cadena. Lo que está codificado es función <nombre>, valor de parámetros.
Impresionante, gran cosa para saber. Parece que estará bien tratando de decodificarlo siempre que el contrato no intente ocultar intencionalmente las entradas
Incluso en este caso, no me importa demasiado. Extraeré la entrada y la ofreceré a los usuarios, ya que es posible que tengan autoridad para acceder a ella que mi aplicación de servidor no tiene.
    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));    

Creo que esto te ayudará

La lógica que he utilizado es la siguiente:

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);
}

Tenía el mismo requisito y comencé a piratear esto en el generador de envoltura de contrato web3j. Debido al enfoque demasiado complicado (en mi humilde opinión), abandoné esto y en su lugar escribí mi propia biblioteca java independiente para esto. No necesita web3j en absoluto, solo necesitará el ABI de Contract en formato JSON.

https://github.com/rvullriede/evm-abi-decodificador

Ejemplo de uso:

// 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

Todavía es un proyecto joven, si encuentra problemas (por ejemplo, con contratos específicos), hágamelo saber a través del rastreador de problemas del proyecto github.

¡Espero que ayude!

No copie y pegue la misma respuesta varias veces. Se marcarán como spam.
¡Gracias por la pista! Solo estaba tratando de ayudar también en la otra pregunta. Voy a vincular a este hilo en su lugar.