nebulasio / neb.java

Java implementation of the Nebulas protocol
GNU Lesser General Public License v3.0
31 stars 18 forks source link

求解!Transaction,如何生成Data #9

Open antgan opened 6 years ago

antgan commented 6 years ago

Data是为了SendTransactionWithPassphrase

yupnano commented 6 years ago

SendTransactionWithPassphrase 不需要data呀。 你是说的 SendRawTransaction 吗?

antgan commented 6 years ago

是的是的!!那个SendRawTransaction的Data怎么来!我试了好多次都不行。

我指的是call contract function

antgan commented 6 years ago

Hope your reply! 几天没睡好!我通过AccountManager生成Address,生成了Sign。然后怎么变成Data

yupnano commented 6 years ago

call conract function 是指的哪个接口呀? 是指的 rpc 的 call 接口吗? https://github.com/nebulasio/nebulasj/blob/master/src/test/java/io/nebulas/client/TestNebulasClient.java#L39

antgan commented 6 years ago

我指这个testSendRawTransaction的Data。 难道是我理解错了吗。调用contract的方法,并且生效(上链)。需要SendRawTransaction

就像官方的Web-wallet 测试合约一样,点击测试按钮,只是调用call,如果点击部署,会SendRawTransaction,上链。

antgan commented 6 years ago

我是这样的一个应用场景: 我在Java设置了个定时器,定时触发去调用一个Contract里的方法,但是如果单单只是call的话,是无效的。

yupnano commented 6 years ago

我刚找了一下,的确缺少这方面的例子。稍后我会补充上使用示例。 现在你可以尝试这样做,结合TransactionExample.java

Transaction tx = new Transaction(chainID, from, to, value, nonce, payloadType, payload, gasPrice, gasLimit);
manager.signTransaction(tx,passphrase);
byte[] rawData = tx.toProto();

//用下面这条指令得到rawData, 然后就可以用 SendRawTransaction 去发送了.
//需要import io.nebulas.util.ByteUtils;
String rawData = ByteUtils.Base64ToString(rawData);
antgan commented 6 years ago

payloadType, payload分别是什么。PayloadType应该是Call,那payload呢。调用合约的方法

antgan commented 6 years ago

是这个呢?

{"transaction":{"from":"n1LkDi2gGMqPrjYcczUiweyP4RxTB6Go1qS","to":"n1rVLTRxQEXscTgThmbTnn2NqdWFEKwpYUM", "value":"0","nonce":2,"gasPrice":"1000000","gasLimit":"2000000","contract":{"function":"takeout","args":"[50]"}}, "passphrase": "passphrase"}

还是

{"from":"n1LkDi2gGMqPrjYcczUiweyP4RxTB6Go1qS","to":"n1rVLTRxQEXscTgThmbTnn2NqdWFEKwpYUM","value":"0","nonce":3,"gasPrice":"1000000","gasLimit":"2000000","contract":{"function":"balanceOf","args":""}}
yupnano commented 6 years ago

你看一下这个例子,TransactionExample.java,里面有如何构建binary、call、deploy三种类型的transaction。 比如call类型的transaction:

payloadType = Transaction.PayloadType.CALL;
payload = new TransactionCallPayload("function", "").toBytes();
to = Address.ParseFromString("n1g6JZsQS1uRUySdwvuFJ7FYT4dFoyoSN5q");
tx = new Transaction(chainID, from, to, value, nonce, payloadType, payload, gasPrice, gasLimit);
antgan commented 6 years ago

非常感谢!我的问题已经得到解答!今晚试试。

antgan commented 6 years ago

@yupnano Hi, NebulasClient中的SendRawTransaction和使用Grpc 有什么区别?

我已经尝试过使用NebulasClient中的SendRawTransaction, 返回null

private static byte[] passphrase = "passphrase".getBytes();

    private static NebulasClient nebulasClient = HttpNebulasClient.create(Config.API_URL);
    public static void main(String args[]) throws Exception {
        AccountManager manager = new AccountManager();
        NebState nebState = nebulasClient.getNebState().getResult();
        // binary tx
        int chainID = nebState.getChainId(); //1 mainet,1001 testnet, 100 default private
        Address from = manager.newAccount(passphrase);
        //Address to = manager.newAccount("topassphrase".getBytes());
        BigInteger value = new BigInteger("0");
        long nonce = 1; // nonce = from.nonce + 1
        BigInteger gasPrice = new BigInteger("1000000"); // 0 < gasPrice < 10^12
        BigInteger gasLimit = new BigInteger("20000"); // 20000 < gasPrice < 50*10^9
        // call tx
        Transaction.PayloadType payloadType = Transaction.PayloadType.CALL;
        byte[] payload = new TransactionCallPayload("award", "").toBytes();
        // call to = contract address
        Address to = Address.ParseFromString("n1jFA5H9MwvfUCUChdav5DmJz51KDrhC7Bq");
        Transaction tx = new Transaction(chainID, from, to, value, nonce, payloadType, payload, gasPrice, gasLimit);
        manager.signTransaction(tx,passphrase);
        byte[] rawData = tx.toProto();
        // senrawTransaction with @rawData
        // https://github.com/nebulasio/wiki/blob/master/rpc.md#sendrawtransaction
        SendRawTransaction(rawData);
    }

    private static void SendRawTransaction(byte[] data) throws Exception {
        // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
        // needing certificates.
//        ManagedChannel channel = ManagedChannelBuilder.forAddress(Config.API_URL, 8684).usePlaintext().build();
//        Rpc.SendRawTransactionRequest request = Rpc.SendRawTransactionRequest
//                .newBuilder()
//                .setData(ByteString.copyFrom(data))
//                .build();
//
//        ApiServiceGrpc.ApiServiceBlockingStub apiServiceStub = ApiServiceGrpc.newBlockingStub(channel);
//        Rpc.SendTransactionResponse response = apiServiceStub.sendRawTransaction(request);
//        System.out.println(response);

        Response<RawTransaction> rawTransactionResponse = nebulasClient.sendRawTransaction(new SendRawTransactionRequest(ByteUtils.Base64ToString(data)));
        System.out.println(rawTransactionResponse);

    }

Return:

Response(error=null, result=RawTransaction(txHash=null, contractAddress=))
antgan commented 6 years ago

补充一下:如果用Grpc的方式,主网和测试网的地址填什么~

antgan commented 6 years ago

补充:没事了,log显示已经成功了。但是Json转Response可能有点问题。都是null

19:26:38.520 [main] DEBUG io.nebulas.client.http.OKHttpClient - http response code : 200
19:26:39.120 [main] DEBUG io.nebulas.client.http.OKHttpClient - http result : {"result":{"chain_id":1,"tail":"ec7e7e84e99a1b004ae52279c7425ff9ec35f9689957d2aac901eadaa15447e9","lib":"0bb6ec25fabdbd510c7b0766a65b01175a15d3654f2674f3e95e491bb3a8bee5","height":"393065","protocol_version":"/neb/1.0.0","synchronized":false,"version":"1.0.1"}}
19:26:39.937 [main] DEBUG io.nebulas.client.http.OKHttpClient - http response code : 200
19:26:40.558 [main] DEBUG io.nebulas.client.http.OKHttpClient - http result : {"result":{"txhash":"cbd378716f7d0a13c3a85e9af7e5425616cf10a35317f180a2b1dac00ddb078a","contract_address":""}}
Response(error=null, result=RawTransaction(txHash=null, contractAddress=))
antgan commented 6 years ago

BUG:真正返回的Response JSON为

{"result":{"txhash":"8423a458b61de581b9c968fb52606d3ec6addb61655346a0f85fe567bc61db2a","contract_address":""}}

txhash和txHash不匹配导致的。

而RawTransaction.java少了 @SerializedName("txhash")

yupnano commented 6 years ago

谢谢反馈,我们马上检查一下这个地方。

yupnano commented 6 years ago

@antgan 已经修复了,是由于大小写没匹配上,导致反序列化失败。很抱歉哈~

antgan commented 6 years ago

没事~哈哈。我自己下载源码 修改打包用了

yupnano commented 6 years ago

关于这个问题:“如果用Grpc的方式,主网和测试网的地址填什么” 主网和测试网的域名是用于HTTP的方式访问的,grpc的话需要填IP和端口号,不建议用grpc访问主网,最好搭建本地节点。

qq364390162 commented 6 years ago

// call tx Transaction.PayloadType payloadType = Transaction.PayloadType.CALL; byte[] payload = new TransactionCallPayload("award", "").toBytes(); // call to = contract address Address to = Address.ParseFromString("n1jFA5H9MwvfUCUChdav5DmJz51KDrhC7Bq"); Transaction tx = new Transaction(chainID, from, to, value, nonce, payloadType, payload, gasPrice, gasLimit); manager.signTransaction(tx,passphrase);

加粗的这个award是一个function,这个function是哪里的,我使用官方的demo测试一只提示Response(error=contract check failed, result=null) @yupnano 麻烦帮忙看一下是什么问题,谢谢

qywang2012 commented 6 years ago

function是部署在主网/测试网的合约方法,调用合约方法需要先成功部署合约

qq364390162 commented 6 years ago

@qywang2012 谢谢,我明白了,我查一下智能合约的部署文档

qq364390162 commented 6 years ago

TransactionExample.java,构建binary、call、deploy三种类型的transaction,代码执行成功以后tx不能成功会停留一段时间的pending状态,最后就没有了是什么问题 @qywang2012 @yupnano ,遇到同样问题的麻烦帮忙解答一下,谢谢