Skip to content

Commit

Permalink
Merge pull request #237 from nervosnetwork/rc/v0.24.9
Browse files Browse the repository at this point in the history
[ᚬmaster] Rc/v0.24.9
  • Loading branch information
quake authored Nov 13, 2019
2 parents 4ca4e41 + fa0114f commit 132a864
Show file tree
Hide file tree
Showing 14 changed files with 351 additions and 39 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [v0.24.9](https://github.com/nervosnetwork/ckb-sdk-java/compare/v0.24.8...v0.24.9) (2019-11-13)

### Feature

* Impl indexer to collect cells and send transaction ([cdbe0a0](https://github.com/nervosnetwork/ckb-sdk-java/commit/cdbe0a0a793033b34ddfcffaa267250ff864636d))


# [v0.24.8](https://github.com/nervosnetwork/ckb-sdk-java/compare/v0.24.7...v0.24.8) (2019-11-13)

### BugFix
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

Java SDK for Nervos [CKB](https://github.com/nervosnetwork/ckb).

The ckb-sdk-java is still under development and **NOT** production ready. You should get familiar with CKB transaction structure and RPC before using it.

### Prerequisites

* Java 8
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ buildscript {
}

plugins {
id 'com.github.johnrengelman.shadow' version '5.1.0'
id 'com.github.johnrengelman.shadow' version '5.2.0'
id 'java'
id 'com.github.sherter.google-java-format' version '0.8'
id 'com.jfrog.bintray' version '1.8.4'
Expand All @@ -43,7 +43,7 @@ allprojects {
targetCompatibility = 1.8

group 'org.nervos.ckb'
version '0.24.8'
version '0.24.9'

apply plugin: 'java'

Expand Down Expand Up @@ -113,7 +113,7 @@ configure(subprojects.findAll { it.name != 'tests' }) {
publications {
mavenJava(MavenPublication) {
groupId 'org.nervos.ckb'
version '0.24.8'
version '0.24.9'
from components.java
}
}
Expand Down
6 changes: 5 additions & 1 deletion ckb/src/main/java/org/nervos/ckb/transaction/LockUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ public static Script generateLockScriptWithPrivateKey(String privateKey, String
return new Script(codeHash, blake160, Script.TYPE);
}

public static Script generateLockScriptWithAddress(String address, String codeHash) {
public static Script generateLockScriptWithAddress(String address) {
AddressParseResult addressParseResult = AddressParser.parse(address);
return addressParseResult.script;
}

public static String generateLockHashWithAddress(String address) {
return generateLockScriptWithAddress(address).computeHash();
}
}
1 change: 1 addition & 0 deletions ckb/src/main/java/org/nervos/ckb/type/cell/LiveCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public class LiveCell {
@SerializedName("created_by")
public TransactionPoint createdBy;

@SerializedName("cell_output")
public CellOutput cellOutput;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.nervos.ckb.type.Witness;
import org.nervos.ckb.type.cell.CellOutput;
import org.nervos.ckb.type.transaction.Transaction;
import org.nervos.ckb.utils.Utils;

/** Copyright © 2019 Nervos Foundation. All rights reserved. */
public class MultiKeySingleSigTxExample {
Expand Down Expand Up @@ -49,9 +50,9 @@ public static void main(String[] args) throws Exception {
String minerAddress = "ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83";
List<Receiver> receivers1 =
Arrays.asList(
new Receiver(Addresses.get(0), new BigInteger("800").multiply(UnitCKB)),
new Receiver(Addresses.get(1), new BigInteger("900").multiply(UnitCKB)),
new Receiver(Addresses.get(2), new BigInteger("1000").multiply(UnitCKB)));
new Receiver(Addresses.get(0), Utils.ckbToShannon(800)),
new Receiver(Addresses.get(1), Utils.ckbToShannon(900)),
new Receiver(Addresses.get(2), Utils.ckbToShannon(1000)));

System.out.println(
"Before transfer, miner's balance: "
Expand All @@ -77,9 +78,9 @@ public static void main(String[] args) throws Exception {

List<Receiver> receivers2 =
Arrays.asList(
new Receiver(Addresses.get(3), new BigInteger("400").multiply(UnitCKB)),
new Receiver(Addresses.get(4), new BigInteger("500").multiply(UnitCKB)),
new Receiver(Addresses.get(5), new BigInteger("600").multiply(UnitCKB)));
new Receiver(Addresses.get(3), Utils.ckbToShannon(400)),
new Receiver(Addresses.get(4), Utils.ckbToShannon(500)),
new Receiver(Addresses.get(5), Utils.ckbToShannon(600)));

String changeAddress = "ckt1qyqfnym6semhw2vzm33fjvk3ngxuf5433l9qz3af8a";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.nervos.ckb.type.cell.CellOutput;
import org.nervos.ckb.type.transaction.Transaction;
import org.nervos.ckb.utils.Numeric;
import org.nervos.ckb.utils.Utils;
import org.nervos.ckb.utils.address.AddressGenerator;

/** Copyright © 2019 Nervos Foundation. All rights reserved. */
Expand Down Expand Up @@ -66,8 +67,7 @@ public static void main(String[] args) throws Exception {
+ getBalance(targetAddress).divide(UnitCKB).toString()
+ " CKB");

String txHash =
sendCapacity(targetAddress, UnitCKB.multiply(BigInteger.valueOf(3000)), privateKeys);
String txHash = sendCapacity(targetAddress, Utils.ckbToShannon(3000), privateKeys);
System.out.println("Transaction hash: " + txHash);
Thread.sleep(30000);
System.out.println(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.nervos.ckb.transaction.*;
import org.nervos.ckb.type.Witness;
import org.nervos.ckb.type.cell.CellOutput;
import org.nervos.ckb.utils.Utils;

/** Copyright © 2019 Nervos Foundation. All rights reserved. */
public class SendToMultiSigAddressTxExample {
Expand All @@ -28,8 +29,7 @@ public class SendToMultiSigAddressTxExample {

public static void main(String[] args) throws Exception {
List<Receiver> receivers =
Collections.singletonList(
new Receiver(MultiSigAddress, new BigInteger("20000").multiply(UnitCKB)));
Collections.singletonList(new Receiver(MultiSigAddress, Utils.ckbToShannon(20000)));

System.out.println(
"Before transfer, miner's balance: " + getBalance().divide(UnitCKB).toString(10) + " CKB");
Expand Down Expand Up @@ -80,7 +80,7 @@ private static String sendCapacity(List<Receiver> receivers, String changeAddres
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);

// // initial_length = 2 * secp256k1_signature_byte.length
// initial_length = 2 * secp256k1_signature_byte.length
List<CellsWithAddress> cellsWithAddresses =
txUtils.collectInputs(
Collections.singletonList(MinerAddress), cellOutputs, feeRate, Sign.SIGN_LENGTH * 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.nervos.ckb.transaction.*;
import org.nervos.ckb.type.Witness;
import org.nervos.ckb.type.cell.CellOutput;
import org.nervos.ckb.utils.Utils;

/** Copyright © 2019 Nervos Foundation. All rights reserved. */
public class SingleKeySingleSigTxExample {
Expand All @@ -34,8 +35,8 @@ public class SingleKeySingleSigTxExample {
public static void main(String[] args) throws Exception {
List<Receiver> receivers =
Arrays.asList(
new Receiver(ReceiveAddresses.get(0), new BigInteger("8000").multiply(UnitCKB)),
new Receiver(ReceiveAddresses.get(1), new BigInteger("9000").multiply(UnitCKB)));
new Receiver(ReceiveAddresses.get(0), Utils.ckbToShannon(8000)),
new Receiver(ReceiveAddresses.get(1), Utils.ckbToShannon(9000)));

System.out.println(
"Before transfer, miner's balance: "
Expand Down Expand Up @@ -81,7 +82,7 @@ private static String sendCapacity(List<Receiver> receivers, String changeAddres
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);

// // initial_length = 2 * secp256k1_signature_byte.length
// initial_length = 2 * secp256k1_signature_byte.length
List<CellsWithAddress> cellsWithAddresses =
txUtils.collectInputs(
Collections.singletonList(MinerAddress), cellOutputs, feeRate, Sign.SIGN_LENGTH * 2);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.nervos.ckb;

import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.nervos.ckb.crypto.secp256k1.Sign;
import org.nervos.ckb.service.Api;
import org.nervos.ckb.transaction.*;
import org.nervos.ckb.type.Witness;
import org.nervos.ckb.type.cell.CellOutput;
import org.nervos.ckb.utils.Utils;

/** Copyright © 2019 Nervos Foundation. All rights reserved. */
public class SingleSigWithIndexerTxExample {

private static final String NODE_URL = "http://localhost:8114";
private static final BigInteger UnitCKB = new BigInteger("100000000");
private static Api api;
private static List<String> ReceiveAddresses;
private static String MinerPrivateKey =
"e79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3";
private static String MinerAddress = "ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83";

static {
api = new Api(NODE_URL, false);
ReceiveAddresses =
Arrays.asList(
"ckt1qyqxgp7za7dajm5wzjkye52asc8fxvvqy9eqlhp82g",
"ckt1qyqtnz38fht9nvmrfdeunrhdtp29n0gagkps4duhek");
}

/**
* Note: If you want to use indexer to collect cell quickly, you should call index_lock_hash rpc
* firstly. CKB needs time to execute tagging to live cells, so we suggest that if you want to
* collect live cells, you should await some time after call index_lock_hash rpc.
*/
public static void main(String[] args) throws Exception {

System.out.println("Call index_lock_hash rpc firstly");

// Call index_lock_hash rpc firstly before collecting live cells
// api.indexLockHash(LockUtils.generateLockHashWithAddress(MinerAddress), "0x0");
// Wait some time for ckb to execute tagging to live cells
// Thread.sleep(20000);

List<Receiver> receivers =
Arrays.asList(
new Receiver(ReceiveAddresses.get(0), Utils.ckbToShannon(8000)),
new Receiver(ReceiveAddresses.get(1), Utils.ckbToShannon(9000)));

System.out.println(
"Before transfer, miner's balance: "
+ getBalance(MinerAddress).divide(UnitCKB).toString(10)
+ " CKB");

// miner send capacity to three receiver accounts with 800, 900 and 1000 CKB
String hash = sendCapacity(receivers, MinerAddress);
System.out.println("Transaction hash: " + hash);
Thread.sleep(30000); // waiting transaction into block, sometimes you should wait more seconds

System.out.println(
"After transfer, miner's balance: "
+ getBalance(MinerAddress).divide(UnitCKB).toString(10)
+ " CKB");
}

private static BigInteger getBalance(String address) throws Exception {
CellCollectorWithIndexer cellCollector = new CellCollectorWithIndexer(api);
return cellCollector.getCapacityWithAddress(address);
}

private static String sendCapacity(List<Receiver> receivers, String changeAddress)
throws IOException {
BigInteger needCapacity = BigInteger.ZERO;
List<ScriptGroupWithPrivateKeys> scriptGroupWithPrivateKeysList = new ArrayList<>();
for (Receiver receiver : receivers) {
needCapacity = needCapacity.add(receiver.capacity);
}

TransactionBuilder txBuilder = new TransactionBuilder(api);
CollectUtils txUtils = new CollectUtils(api);

List<CellOutput> cellOutputs = txUtils.generateOutputs(receivers, changeAddress);
txBuilder.addOutputs(cellOutputs);

// You can get fee rate by rpc or set a simple number
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);

// initial_length = 2 * secp256k1_signature_byte.length
// collectInputsWithIndexer method uses indexer rpc to collect cells quickly
List<CellsWithAddress> cellsWithAddresses =
txUtils.collectInputsWithIndexer(
Collections.singletonList(MinerAddress), cellOutputs, feeRate, Sign.SIGN_LENGTH * 2);
int startIndex = 0;
for (CellsWithAddress cellsWithAddress : cellsWithAddresses) {
txBuilder.addInputs(cellsWithAddress.inputs);
for (int i = 0; i < cellsWithAddress.inputs.size(); i++) {
txBuilder.addWitness(i == 0 ? new Witness(Witness.SIGNATURE_PLACEHOLDER) : "0x");
}
scriptGroupWithPrivateKeysList.add(
new ScriptGroupWithPrivateKeys(
new ScriptGroup(NumberUtils.regionToList(startIndex, cellsWithAddress.inputs.size())),
Collections.singletonList(MinerPrivateKey)));
}

Secp256k1SighashAllBuilder signBuilder = new Secp256k1SighashAllBuilder(txBuilder.buildTx());

for (ScriptGroupWithPrivateKeys scriptGroupWithPrivateKeys : scriptGroupWithPrivateKeysList) {
signBuilder.sign(
scriptGroupWithPrivateKeys.scriptGroup, scriptGroupWithPrivateKeys.privateKeys.get(0));
}

return api.sendTransaction(signBuilder.buildTx());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public Map<String, List<CellInput>> collectInputs(
int witnessIndex = 0;
for (String lockHash : lockHashes) {
if (lockInputsMap.get(lockHash).size() == 0) break;
witnesses.set(witnessIndex, new Witness(getZeros(initialLength)));
witnesses.set(witnessIndex, new Witness(NumberUtils.getZeros(initialLength)));
witnessIndex += lockInputsMap.get(lockHash).size();
}
transaction.witnesses = witnesses;
Expand Down Expand Up @@ -164,12 +164,4 @@ public BigInteger getCapacityWithLockHash(String lockHash) throws IOException {
private BigInteger calculateOutputSize(CellOutput cellOutput) {
return BigInteger.valueOf(Serializer.serializeCellOutput(cellOutput).getLength());
}

private String getZeros(int length) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append("0");
}
return sb.toString();
}
}
Loading

0 comments on commit 132a864

Please sign in to comment.