From 8a3143ff96b5feedbe4e6cba577f7204356a74d7 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Tue, 27 Dec 2022 10:49:31 +0800 Subject: [PATCH 01/14] =?UTF-8?q?chore:=20=F0=9F=A4=96=20Update=20deprecat?= =?UTF-8?q?ed=20gradle=20functions=20to=20new=20ones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In gradle 6.5, testCompile is replaced with testImplementation and testRuntime should be testRuntimeOnly, the 2 functions are all replaced with testImplementation, so will cause something like "The configuration to scope mapping is not unique", and fail to run ./gradlew uploadArchives --- ckb-indexer/build.gradle | 7 ++++--- ckb-mercury-sdk/build.gradle | 8 ++++---- light-client/build.gradle | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ckb-indexer/build.gradle b/ckb-indexer/build.gradle index c938f3d6e..9adc9fcd2 100644 --- a/ckb-indexer/build.gradle +++ b/ckb-indexer/build.gradle @@ -2,11 +2,12 @@ description 'SDK for CKB indexer' dependencies { compile project(":core") - testCompile("org.junit.jupiter:junit-jupiter-api:5.9.0") - testRuntime("org.junit.jupiter:junit-jupiter-engine:5.9.0") + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' // Enable use of the JUnitPlatform Runner within the IDE - testCompile("org.junit.platform:junit-platform-runner:1.9.0") + testImplementation("org.junit.platform:junit-platform-runner:1.9.0") } test { diff --git a/ckb-mercury-sdk/build.gradle b/ckb-mercury-sdk/build.gradle index 733532cc2..3fba88f21 100644 --- a/ckb-mercury-sdk/build.gradle +++ b/ckb-mercury-sdk/build.gradle @@ -3,11 +3,11 @@ description 'SDK for CKB mercury' dependencies { compile project(":core") compile project(":ckb-indexer") - testCompile project(":ckb") - testCompile("org.junit.jupiter:junit-jupiter-api:5.9.0") - testRuntime("org.junit.jupiter:junit-jupiter-engine:5.9.0") + testImplementation project(":ckb") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.0") // Enable use of the JUnitPlatform Runner within the IDE - testCompile("org.junit.platform:junit-platform-runner:1.9.0") + testImplementation("org.junit.platform:junit-platform-runner:1.9.0") } test { diff --git a/light-client/build.gradle b/light-client/build.gradle index 3d7449f8b..04c688523 100644 --- a/light-client/build.gradle +++ b/light-client/build.gradle @@ -11,8 +11,8 @@ repositories { dependencies { implementation project(":ckb-indexer") - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' } test { From 5b4ac474d915f496eb45fd5055dcab51209894d0 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Tue, 27 Dec 2022 18:27:56 +0800 Subject: [PATCH 02/14] =?UTF-8?q?test:=20=F0=9F=92=8D=20Disable=20unittest?= =?UTF-8?q?=20since=20test=20indexer=20point=20to=20ckb=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ckb-indexer/src/test/java/indexer/TipTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ckb-indexer/src/test/java/indexer/TipTest.java b/ckb-indexer/src/test/java/indexer/TipTest.java index b55882a10..1f68dcda6 100644 --- a/ckb-indexer/src/test/java/indexer/TipTest.java +++ b/ckb-indexer/src/test/java/indexer/TipTest.java @@ -26,6 +26,9 @@ void getTip() throws IOException { Assertions.assertTrue(tip.blockNumber <= tip2.blockNumber); } + // both testnet and mainnet indexer url point to the ckb module ones, so no get_tip exist, it's get_indexer_tip, + // so if you use a old standalone ckb-indexer, should Configuration.setIndexerUrl yourself. + @Disabled @Test void getTipStandAlone() throws IOException { Configuration.getInstance().setIndexType(IndexerType.StandAlone); From c281e32552e996e51f474ac3f320aaf2a6fd4873 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Fri, 13 Jan 2023 10:02:02 +0800 Subject: [PATCH 03/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20enable=20with=5Fcy?= =?UTF-8?q?cles=20of=20get=5Fblock=20and=20get=5Fblock=5Fby=5Fnumber?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ build.gradle | 2 +- .../main/java/org/nervos/ckb/CkbRpcApi.java | 2 ++ .../main/java/org/nervos/ckb/service/Api.java | 14 +++++++++++++- ckb/src/test/java/service/ApiTest.java | 19 +++++++++++++++++++ .../org/nervos/ckb/type/BlockResponse.java | 16 ++++++++++++++++ 6 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/nervos/ckb/type/BlockResponse.java diff --git a/CHANGELOG.md b/CHANGELOG.md index a6d937703..e25a99086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 2.1.1 (2023-01-16) +- feat: support with_cycles for get_block and get_block_by_number rpc + +## 🚀 Features # 2.1.0 (2022-12-26) ## 🚀 Features diff --git a/build.gradle b/build.gradle index 36c9fc613..f32ec82fe 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ allprojects { targetCompatibility = 1.8 group 'org.nervos.ckb' - version '2.1.0' + version '2.1.1' apply plugin: 'java' repositories { diff --git a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java index ee724e354..60abf6a8d 100644 --- a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java +++ b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java @@ -11,8 +11,10 @@ public interface CkbRpcApi { Block getBlock(byte[] blockHash) throws IOException; + BlockResponse getBlock(byte[] blockHash, Boolean with_cycles) throws IOException; Block getBlockByNumber(long blockNumber) throws IOException; + BlockResponse getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException; TransactionWithStatus getTransaction(byte[] transactionHash) throws IOException; diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index 774fa44ef..9554eb4de 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -34,12 +34,24 @@ public Block getBlock(byte[] blockHash) throws IOException { return rpcService.post("get_block", Collections.singletonList(blockHash), Block.class); } + @Override + public BlockResponse getBlock(byte[] blockHash, Boolean with_cycles) throws IOException { + List params = with_cycles == null ? Collections.singletonList(blockHash): Arrays.asList(blockHash,null, with_cycles); + return rpcService.post("get_block", params, BlockResponse.class); + } + @Override public Block getBlockByNumber(long blockNumber) throws IOException { return rpcService.post( "get_block_by_number", Collections.singletonList(blockNumber), Block.class); } + @Override + public BlockResponse getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException { + List params = with_cycles == null ? Collections.singletonList(blockNumber): Arrays.asList(blockNumber,null, with_cycles); + return rpcService.post("get_block_by_number", params, BlockResponse.class); + } + @Override public TransactionWithStatus getTransaction(byte[] transactionHash) throws IOException { return rpcService.post( @@ -261,7 +273,7 @@ public Cycles estimateCycles(Transaction transaction) throws IOException { @Override public TipResponse getIndexerTip() throws IOException { - return this.rpcService.post("get_indexer_tip", Arrays.asList(), TipResponse.class); + return this.rpcService.post("get_indexer_tip", Collections.emptyList(), TipResponse.class); } @Override diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index 843aff2d1..082bb07a6 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -33,6 +33,14 @@ public void testGetBlockByNumber() throws IOException { Assertions.assertEquals(1, block.transactions.size()); } + @Test + public void testGetBlockByNumberWithCycles() throws IOException { + BlockResponse response = api.getBlockByNumber(7981482, true); + Assertions.assertEquals(response.cycles.size() + 1, response.block.transactions.size()); + Assertions.assertTrue(response.cycles.size() > 0); + } + + @Test public void testGetBlockHashByNumber() throws IOException { byte[] blockHash = api.getBlockHash(1); @@ -60,6 +68,17 @@ public void testGetBlock() throws IOException { Assertions.assertNotNull(block.header); } + @Test + public void testGetBlockWithCycles() throws IOException { + byte[] blockHash = + Numeric.hexStringToByteArray( + "0xd88eb0cf9f6e6f123c733e9aba29dec9cb449965a8adc98216c50d5083b909b1"); + BlockResponse response = api.getBlock(blockHash, true); + Assertions.assertEquals(response.cycles.size() + 1, response.block.transactions.size()); + Assertions.assertTrue(response.cycles.size() > 0); + Assertions.assertNotNull(response.block.header); + } + @Test public void testTransaction() throws IOException { byte[] transactionHash = diff --git a/core/src/main/java/org/nervos/ckb/type/BlockResponse.java b/core/src/main/java/org/nervos/ckb/type/BlockResponse.java new file mode 100644 index 000000000..bd724c9ff --- /dev/null +++ b/core/src/main/java/org/nervos/ckb/type/BlockResponse.java @@ -0,0 +1,16 @@ +package org.nervos.ckb.type; + +import java.util.List; + +public class BlockResponse { + /** + * infomation of the block + */ + public Block block; + + /** + * The cycles of each transaction. + * Note: cell base transaction has no cycle, so cycles' size is one less than block.transactions. + */ + public List cycles; +} From 85e6305de017c0a8374a96c545bdd15a8d47c5c2 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Wed, 1 Feb 2023 16:39:13 +0800 Subject: [PATCH 04/14] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Rename=20Block?= =?UTF-8?q?Response=20to=20BlockWithCycles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java | 4 ++-- ckb/src/main/java/org/nervos/ckb/service/Api.java | 8 ++++---- ckb/src/test/java/service/ApiTest.java | 4 ++-- .../ckb/type/{BlockResponse.java => BlockWithCycles.java} | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) rename core/src/main/java/org/nervos/ckb/type/{BlockResponse.java => BlockWithCycles.java} (91%) diff --git a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java index 60abf6a8d..094673701 100644 --- a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java +++ b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java @@ -11,10 +11,10 @@ public interface CkbRpcApi { Block getBlock(byte[] blockHash) throws IOException; - BlockResponse getBlock(byte[] blockHash, Boolean with_cycles) throws IOException; + BlockWithCycles getBlock(byte[] blockHash, Boolean with_cycles) throws IOException; Block getBlockByNumber(long blockNumber) throws IOException; - BlockResponse getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException; + BlockWithCycles getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException; TransactionWithStatus getTransaction(byte[] transactionHash) throws IOException; diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index 9554eb4de..a6b9f7bbb 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -35,9 +35,9 @@ public Block getBlock(byte[] blockHash) throws IOException { } @Override - public BlockResponse getBlock(byte[] blockHash, Boolean with_cycles) throws IOException { + public BlockWithCycles getBlock(byte[] blockHash, Boolean with_cycles) throws IOException { List params = with_cycles == null ? Collections.singletonList(blockHash): Arrays.asList(blockHash,null, with_cycles); - return rpcService.post("get_block", params, BlockResponse.class); + return rpcService.post("get_block", params, BlockWithCycles.class); } @Override @@ -47,9 +47,9 @@ public Block getBlockByNumber(long blockNumber) throws IOException { } @Override - public BlockResponse getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException { + public BlockWithCycles getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException { List params = with_cycles == null ? Collections.singletonList(blockNumber): Arrays.asList(blockNumber,null, with_cycles); - return rpcService.post("get_block_by_number", params, BlockResponse.class); + return rpcService.post("get_block_by_number", params, BlockWithCycles.class); } @Override diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index 082bb07a6..dba91ea0e 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -35,7 +35,7 @@ public void testGetBlockByNumber() throws IOException { @Test public void testGetBlockByNumberWithCycles() throws IOException { - BlockResponse response = api.getBlockByNumber(7981482, true); + BlockWithCycles response = api.getBlockByNumber(7981482, true); Assertions.assertEquals(response.cycles.size() + 1, response.block.transactions.size()); Assertions.assertTrue(response.cycles.size() > 0); } @@ -73,7 +73,7 @@ public void testGetBlockWithCycles() throws IOException { byte[] blockHash = Numeric.hexStringToByteArray( "0xd88eb0cf9f6e6f123c733e9aba29dec9cb449965a8adc98216c50d5083b909b1"); - BlockResponse response = api.getBlock(blockHash, true); + BlockWithCycles response = api.getBlock(blockHash, true); Assertions.assertEquals(response.cycles.size() + 1, response.block.transactions.size()); Assertions.assertTrue(response.cycles.size() > 0); Assertions.assertNotNull(response.block.header); diff --git a/core/src/main/java/org/nervos/ckb/type/BlockResponse.java b/core/src/main/java/org/nervos/ckb/type/BlockWithCycles.java similarity index 91% rename from core/src/main/java/org/nervos/ckb/type/BlockResponse.java rename to core/src/main/java/org/nervos/ckb/type/BlockWithCycles.java index bd724c9ff..250d1f080 100644 --- a/core/src/main/java/org/nervos/ckb/type/BlockResponse.java +++ b/core/src/main/java/org/nervos/ckb/type/BlockWithCycles.java @@ -2,7 +2,7 @@ import java.util.List; -public class BlockResponse { +public class BlockWithCycles { /** * infomation of the block */ From 312a258ba59ae8a0287aa060fa27e50abcbd656c Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Thu, 2 Feb 2023 10:11:52 +0800 Subject: [PATCH 05/14] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Pack=20uint32(-1)?= =?UTF-8?q?=20into=200xffffffff=20instead=20of=200xff000000?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/nervos/ckb/utils/MoleculeConverter.java | 16 ++++++++++++++-- .../main/java/org/nervos/ckb/utils/Numeric.java | 7 ++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java b/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java index 297ef4c51..fa3ba93d7 100644 --- a/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java +++ b/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java @@ -16,12 +16,24 @@ public static byte[] toByteArrayLittleEndianUnsigned(BigInteger in, int length) } public static Uint32 packUint32(int in) { - byte[] arr = toByteArrayLittleEndianUnsigned(BigInteger.valueOf(in), Uint32.SIZE); + byte[] arr = new byte[Integer.BYTES]; + arr[3] = (byte) (in >> Byte.SIZE * 3); + arr[2] = (byte) (in >> Byte.SIZE * 2); + arr[1] = (byte) (in >> Byte.SIZE); + arr[0] = (byte) in; return Uint32.builder(arr).build(); } public static Uint64 packUint64(long in) { - byte[] arr = toByteArrayLittleEndianUnsigned(BigInteger.valueOf(in), Uint64.SIZE); + byte[] arr = new byte[Long.BYTES]; + arr[7] = (byte) (in >> Byte.SIZE * 7); + arr[6] = (byte) (in >> Byte.SIZE * 6); + arr[5] = (byte) (in >> Byte.SIZE * 5); + arr[4] = (byte) (in >> Byte.SIZE * 4); + arr[3] = (byte) (in >> Byte.SIZE * 3); + arr[2] = (byte) (in >> Byte.SIZE * 2); + arr[1] = (byte) (in >> Byte.SIZE); + arr[0] = (byte) in; return Uint64.builder(arr).build(); } diff --git a/utils/src/main/java/org/nervos/ckb/utils/Numeric.java b/utils/src/main/java/org/nervos/ckb/utils/Numeric.java index 7f75ce555..66b1a71aa 100644 --- a/utils/src/main/java/org/nervos/ckb/utils/Numeric.java +++ b/utils/src/main/java/org/nervos/ckb/utils/Numeric.java @@ -65,7 +65,7 @@ public static String prependHexPrefix(String input) { } public static boolean containsHexPrefix(String input) { - return input.length() > 1 && input.charAt(0) == '0' && input.charAt(1) == 'x'; + return input.length() > 1 && input.charAt(0) == '0' && (input.charAt(1) == 'x' || input.charAt(1) == 'X'); } public static BigInteger toBigInt(byte[] value, int offset, int length) { @@ -149,6 +149,11 @@ public static byte[] toBytesPadded(BigInteger value, int length) { } int destOffset = length - bytesLength; + if (value.signum() < 0) { + // signum expand + for (int i = 0, len = 0; i < destOffset; i++) + result[i] = (byte)0xff; + } System.arraycopy(bytes, srcOffset, result, destOffset, bytesLength); return result; } From 81bf4f971491f617ec965c7b6e085857a7c5d06b Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Thu, 2 Feb 2023 20:38:55 +0800 Subject: [PATCH 06/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20get=20packed?= =?UTF-8?q?=20version=20getblock=20and=20gettransaction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. getPackedBlock/getPackedBlockByNumber/getPackedTransaction 2. Fix the problem when with_cycle is false, json deserilize failed problem. --- .../main/java/org/nervos/ckb/CkbRpcApi.java | 8 +- .../main/java/org/nervos/ckb/service/Api.java | 56 +++++++++++-- ckb/src/test/java/service/ApiTest.java | 79 +++++++++++++++---- .../main/java/org/nervos/ckb/type/Block.java | 31 ++++++++ .../ckb/type/PackedBlockWithCycles.java | 25 ++++++ .../ckb/type/PackedTransactionWithStatus.java | 16 ++++ .../nervos/ckb/utils/MoleculeConverter.java | 32 ++++++++ .../org/nervos/ckb/type/concrete/Block.java | 27 +++++++ .../org/nervos/ckb/type/concrete/BlockV1.java | 4 + .../org/nervos/ckb/utils/NumericTest.java | 14 ++++ 10 files changed, 267 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java create mode 100644 core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java diff --git a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java index 094673701..ee0535939 100644 --- a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java +++ b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java @@ -11,13 +11,15 @@ public interface CkbRpcApi { Block getBlock(byte[] blockHash) throws IOException; - BlockWithCycles getBlock(byte[] blockHash, Boolean with_cycles) throws IOException; + BlockWithCycles getBlock(byte[] blockHash, boolean with_cycles) throws IOException; + PackedBlockWithCycles getPackedBlock(byte[] blockHash, boolean with_cycles) throws IOException; Block getBlockByNumber(long blockNumber) throws IOException; - BlockWithCycles getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException; + BlockWithCycles getBlockByNumber(long blockNumber, boolean with_cycles) throws IOException; + PackedBlockWithCycles getPackedBlockByNumber(long blockNumber, boolean with_cycles) throws IOException; TransactionWithStatus getTransaction(byte[] transactionHash) throws IOException; - + PackedTransactionWithStatus getPackedTransaction(byte[] transactionHash) throws IOException; byte[] getBlockHash(long blockNumber) throws IOException; BlockEconomicState getBlockEconomicState(byte[] blockHash) throws IOException; diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index a6b9f7bbb..6bc1068ea 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -35,9 +35,16 @@ public Block getBlock(byte[] blockHash) throws IOException { } @Override - public BlockWithCycles getBlock(byte[] blockHash, Boolean with_cycles) throws IOException { - List params = with_cycles == null ? Collections.singletonList(blockHash): Arrays.asList(blockHash,null, with_cycles); - return rpcService.post("get_block", params, BlockWithCycles.class); + public BlockWithCycles getBlock(byte[] blockHash, boolean with_cycles) throws IOException { + List params = Arrays.asList(blockHash, null, with_cycles); + if (with_cycles) { + return rpcService.post("get_block", params, BlockWithCycles.class); + } else { + Block block = rpcService.post("get_block", params, Block.class); + BlockWithCycles ret = new BlockWithCycles(); + ret.block = block; + return ret; + } } @Override @@ -47,9 +54,41 @@ public Block getBlockByNumber(long blockNumber) throws IOException { } @Override - public BlockWithCycles getBlockByNumber(long blockNumber, Boolean with_cycles) throws IOException { - List params = with_cycles == null ? Collections.singletonList(blockNumber): Arrays.asList(blockNumber,null, with_cycles); - return rpcService.post("get_block_by_number", params, BlockWithCycles.class); + public BlockWithCycles getBlockByNumber(long blockNumber, boolean with_cycles) throws IOException { + List params = Arrays.asList(blockNumber, null, with_cycles); + if (with_cycles) { + return rpcService.post("get_block_by_number", params, BlockWithCycles.class); + } else { + Block block = rpcService.post("get_block_by_number", params, Block.class); + BlockWithCycles ret = new BlockWithCycles(); + ret.block = block; + return ret; + } + } + + @Override + public PackedBlockWithCycles getPackedBlock(byte[] blockHash, boolean with_cycles) throws IOException { + if (with_cycles) { + return rpcService.post("get_block", Arrays.asList(blockHash, 0, true), PackedBlockWithCycles.class); + } else { + String s = rpcService.post("get_block", Arrays.asList(blockHash, 0, false), String.class); + PackedBlockWithCycles ret = new PackedBlockWithCycles(); + ret.block = s; + return ret; + } + } + + @Override + public PackedBlockWithCycles getPackedBlockByNumber(long blockNumber, boolean with_cycles) throws IOException { + List params = Arrays.asList(blockNumber, 0, with_cycles); + if (with_cycles) { + return rpcService.post("get_block_by_number", params, PackedBlockWithCycles.class); + } else { + String s = rpcService.post("get_block_by_number", params, String.class); + PackedBlockWithCycles ret = new PackedBlockWithCycles(); + ret.block = s; + return ret; + } } @Override @@ -58,6 +97,11 @@ public TransactionWithStatus getTransaction(byte[] transactionHash) throws IOExc "get_transaction", Collections.singletonList(transactionHash), TransactionWithStatus.class); } + @Override + public PackedTransactionWithStatus getPackedTransaction(byte[] transactionHash) throws IOException { + return rpcService.post("get_transaction", Arrays.asList(transactionHash, 0), PackedTransactionWithStatus.class); + } + @Override public byte[] getBlockHash(long blockNumber) throws IOException { return rpcService.post("get_block_hash", Collections.singletonList(blockNumber), byte[].class); diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index dba91ea0e..32befbade 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -35,9 +35,23 @@ public void testGetBlockByNumber() throws IOException { @Test public void testGetBlockByNumberWithCycles() throws IOException { - BlockWithCycles response = api.getBlockByNumber(7981482, true); + long blockNumber = 7981482; + BlockWithCycles response = api.getBlockByNumber(blockNumber, true); Assertions.assertEquals(response.cycles.size() + 1, response.block.transactions.size()); Assertions.assertTrue(response.cycles.size() > 0); + + BlockWithCycles response0 = api.getBlockByNumber(blockNumber, false); + Assertions.assertArrayEquals(response0.block.pack().toByteArray(), response.block.pack().toByteArray()); + Assertions.assertNull(response0.cycles); + + PackedBlockWithCycles packedResponse = api.getPackedBlockByNumber(blockNumber, true); + Assertions.assertEquals(Numeric.toHexString(packedResponse.getBlockBytes()), Numeric.toHexString(response.block.pack().toByteArray())); + Assertions.assertArrayEquals(packedResponse.getBlockBytes(), response.block.pack().toByteArray()); + Assertions.assertEquals(response.cycles, packedResponse.cycles); + + PackedBlockWithCycles packedResponse0 = api.getPackedBlockByNumber(blockNumber, false); + Assertions.assertArrayEquals(packedResponse.getBlockBytes(), packedResponse0.getBlockBytes()); + Assertions.assertNull(packedResponse0.cycles); } @@ -66,17 +80,38 @@ public void testGetBlock() throws IOException { Block block = api.getBlock(blockHash); Assertions.assertEquals(1, block.transactions.size()); Assertions.assertNotNull(block.header); + + PackedBlockWithCycles packedBlockBytes = api.getPackedBlock(blockHash, true); + byte[] bytes = packedBlockBytes.getBlockBytes(); + Assertions.assertNotNull(bytes); + Assertions.assertNotNull(packedBlockBytes.cycles); + + PackedBlockWithCycles packedBlockBytes0 = api.getPackedBlock(blockHash, false); + Assertions.assertNull(packedBlockBytes0.cycles); + Assertions.assertEquals(packedBlockBytes.block, packedBlockBytes0.block); + + org.nervos.ckb.type.concrete.Block block_from_molecule = org.nervos.ckb.type.concrete.Block.builder(bytes).build(); + + org.nervos.ckb.type.concrete.Block block_from_json = block.pack(); + + byte[] bytes_from_json = block_from_json.toByteArray(); + Assertions.assertEquals(Numeric.toHexString(bytes), Numeric.toHexString(bytes_from_json)); + Assertions.assertArrayEquals(bytes, bytes_from_json); } @Test public void testGetBlockWithCycles() throws IOException { byte[] blockHash = - Numeric.hexStringToByteArray( - "0xd88eb0cf9f6e6f123c733e9aba29dec9cb449965a8adc98216c50d5083b909b1"); + Numeric.hexStringToByteArray( + "0xd88eb0cf9f6e6f123c733e9aba29dec9cb449965a8adc98216c50d5083b909b1"); BlockWithCycles response = api.getBlock(blockHash, true); Assertions.assertEquals(response.cycles.size() + 1, response.block.transactions.size()); Assertions.assertTrue(response.cycles.size() > 0); Assertions.assertNotNull(response.block.header); + + BlockWithCycles response0 = api.getBlock(blockHash, false); + Assertions.assertArrayEquals(response0.block.pack().toByteArray(), response.block.pack().toByteArray()); + Assertions.assertNull(response0.cycles); } @Test @@ -91,8 +126,8 @@ public void testTransaction() throws IOException { Assertions.assertEquals(30000000000L, transaction.outputs.get(0).capacity); transactionHash = - Numeric.hexStringToByteArray( - "0x3dca00e45e2f3a39d707d5559ba49d27d21038624b0402039898d3a8830525be"); + Numeric.hexStringToByteArray( + "0x3dca00e45e2f3a39d707d5559ba49d27d21038624b0402039898d3a8830525be"); TransactionWithStatus transactionWithStatus = api.getTransaction(transactionHash); Assertions.assertNotNull(transactionWithStatus.txStatus); @@ -100,6 +135,18 @@ public void testTransaction() throws IOException { Assertions.assertTrue(transactionWithStatus.cycles > 0); } + @Test + public void testPackedTransaction() throws IOException { + byte[] transactionHash = + Numeric.hexStringToByteArray( + "0x8277d74d33850581f8d843613ded0c2a1722dec0e87e748f45c115dfb14210f1"); + byte[] transaction_bytes = api.getPackedTransaction(transactionHash).getTransactionBytes(); + + Transaction transaction = api.getTransaction(transactionHash).transaction; + byte[] bytes_from_json = transaction.pack().toByteArray(); + Assertions.assertArrayEquals(bytes_from_json, transaction_bytes); + } + @Test public void testGetTipHeader() throws IOException { Header header = api.getTipHeader(); @@ -275,12 +322,12 @@ public void testGetRawTxPoolVerbose() throws IOException { RawTxPoolVerbose rawTxPoolVerbose = api.getRawTxPoolVerbose(); Assertions.assertNotNull(rawTxPoolVerbose); - for (Map.Entry entry: + for (Map.Entry entry : rawTxPoolVerbose.pending.entrySet()) { Assertions.assertNotNull((entry.getValue())); } - for (Map.Entry entry: + for (Map.Entry entry : rawTxPoolVerbose.proposed.entrySet()) { Assertions.assertNotNull((entry.getValue())); } @@ -472,15 +519,15 @@ public void testDryRunTransaction() throws IOException { @Test public void testEstimateCycles() throws IOException { Cycles cycles = - api.estimateCycles( - new Transaction( - 0, - Collections.emptyList(), - Collections.emptyList(), - Collections.emptyList(), - Collections.emptyList(), - Collections.emptyList(), - Collections.emptyList())); + api.estimateCycles( + new Transaction( + 0, + Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList())); Assertions.assertNotNull(cycles); } diff --git a/core/src/main/java/org/nervos/ckb/type/Block.java b/core/src/main/java/org/nervos/ckb/type/Block.java index 086c2dcfa..86c7a88ba 100644 --- a/core/src/main/java/org/nervos/ckb/type/Block.java +++ b/core/src/main/java/org/nervos/ckb/type/Block.java @@ -2,6 +2,9 @@ import java.util.List; +import org.nervos.ckb.utils.MoleculeConverter; +import org.nervos.ckb.utils.Numeric; + public class Block { public Header header; @@ -11,10 +14,38 @@ public class Block { public List uncles; + public String extension; + public static class Uncle { public Header header; public List proposals; } + + public byte[] getExtensionBytes() { + if (this.extension == null) { + return null; + } + return Numeric.hexStringToByteArray(this.extension); + } + + public org.nervos.ckb.type.concrete.Block pack() { + if (this.extension != null) { + return org.nervos.ckb.type.concrete.BlockV1.builder().setHeader(header.pack()) + .setTransactions(MoleculeConverter.packTransactionVec(transactions)) + .setProposals(MoleculeConverter.packProposalShortIdVec(proposals)) + .setUncles(MoleculeConverter.packUncleBlockVec(uncles)) + .setExtension(MoleculeConverter.packBytes(this.getExtensionBytes())) + .build() + .asV0(); + } else { + return org.nervos.ckb.type.concrete.Block.builder() + .setHeader(header.pack()) + .setTransactions(MoleculeConverter.packTransactionVec(transactions)) + .setProposals(MoleculeConverter.packProposalShortIdVec(proposals)) + .setUncles(MoleculeConverter.packUncleBlockVec(uncles)) + .build(); + } + } } diff --git a/core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java b/core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java new file mode 100644 index 000000000..d788896f5 --- /dev/null +++ b/core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java @@ -0,0 +1,25 @@ +package org.nervos.ckb.type; + +import org.nervos.ckb.utils.Numeric; + +import java.util.List; + +public class PackedBlockWithCycles { + /** + * infomation of the block + */ + public String block; + + /** + * The cycles of each transaction. + * Note: cell base transaction has no cycle, so cycles' size is one less than block.transactions. + */ + public List cycles; + + /** + * @return parsed bytes from block string + */ + public byte[] getBlockBytes() { + return Numeric.hexStringToByteArray(this.block); + } +} diff --git a/core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java b/core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java new file mode 100644 index 000000000..86f6ba1c3 --- /dev/null +++ b/core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java @@ -0,0 +1,16 @@ +package org.nervos.ckb.type; + +import org.nervos.ckb.utils.Numeric; + +public class PackedTransactionWithStatus { + public TransactionWithStatus.TxStatus txStatus; + public String transaction; + public Long cycles; + + /** + * @return parsed bytes from transaction string + */ + public byte[] getTransactionBytes() { + return Numeric.hexStringToByteArray(this.transaction); + } +} diff --git a/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java b/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java index fa3ba93d7..66314a6f1 100644 --- a/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java +++ b/core/src/main/java/org/nervos/ckb/utils/MoleculeConverter.java @@ -92,4 +92,36 @@ public static CellDepVec packCellDepVec(List in) { } return CellDepVec.builder().add(arr).build(); } + + public static TransactionVec packTransactionVec(List transactions) { + TransactionVec.Builder builder = TransactionVec.builder(); + Transaction[] packed_transactions = transactions.stream().map(org.nervos.ckb.type.Transaction::pack).toArray(Transaction[]::new); + builder.add(packed_transactions); + return builder.build(); + } + + public static ProposalShortId packProposalShortId(byte[] shortId) { + return ProposalShortId.builder().set(shortId).build(); + } + + public static ProposalShortIdVec packProposalShortIdVec(List shortIds) { + ProposalShortIdVec.Builder builder = ProposalShortIdVec.builder(); + ProposalShortId[] packed_ids = shortIds.stream().map(MoleculeConverter::packProposalShortId).toArray(ProposalShortId[]::new); + builder.add(packed_ids); + return builder.build(); + } + + public static UncleBlock packUncleBlock(org.nervos.ckb.type.Block.Uncle uncle) { + UncleBlock.Builder builder = UncleBlock.builder(); + builder.setHeader(uncle.header.pack()); + builder.setProposals(packProposalShortIdVec(uncle.proposals)); + return builder.build(); + } + + public static UncleBlockVec packUncleBlockVec(List uncles) { + UncleBlockVec.Builder builder = UncleBlockVec.builder(); + UncleBlock[] packed_uncles = uncles.stream().map(MoleculeConverter::packUncleBlock).toArray(UncleBlock[]::new); + builder.add(packed_uncles); + return builder.build(); + } } diff --git a/serialization/src/main/java/org/nervos/ckb/type/concrete/Block.java b/serialization/src/main/java/org/nervos/ckb/type/concrete/Block.java index 7a73e618f..e53ffab02 100644 --- a/serialization/src/main/java/org/nervos/ckb/type/concrete/Block.java +++ b/serialization/src/main/java/org/nervos/ckb/type/concrete/Block.java @@ -87,6 +87,33 @@ private Builder(@Nonnull byte[] buf) { proposals = ProposalShortIdVec.builder(itemBuf).build(); } + public static Block buildUnchecked(@Nonnull byte[] buf) { + Objects.requireNonNull(buf); + int size = MoleculeUtils.littleEndianBytes4ToInt(buf, 0); + if (buf.length != size) { + throw MoleculeException.invalidByteSize(size, buf.length, Block.class); + } + int[] offsets = MoleculeUtils.getOffsets(buf); + + byte[] itemBuf; + itemBuf = Arrays.copyOfRange(buf, offsets[0], offsets[1]); + Header header = Header.builder(itemBuf).build(); + itemBuf = Arrays.copyOfRange(buf, offsets[1], offsets[2]); + UncleBlockVec uncles = UncleBlockVec.builder(itemBuf).build(); + itemBuf = Arrays.copyOfRange(buf, offsets[2], offsets[3]); + TransactionVec transactions = TransactionVec.builder(itemBuf).build(); + itemBuf = Arrays.copyOfRange(buf, offsets[3], offsets[4]); + ProposalShortIdVec proposals = ProposalShortIdVec.builder(itemBuf).build(); + + Block t = new Block(); + t.buf = buf; + t.header = header; + t.uncles = uncles; + t.transactions = transactions; + t.proposals = proposals; + return t; + } + public Builder setHeader(@Nonnull Header header) { Objects.requireNonNull(header); this.header = header; diff --git a/serialization/src/main/java/org/nervos/ckb/type/concrete/BlockV1.java b/serialization/src/main/java/org/nervos/ckb/type/concrete/BlockV1.java index a3be8f770..b1b97fe5d 100644 --- a/serialization/src/main/java/org/nervos/ckb/type/concrete/BlockV1.java +++ b/serialization/src/main/java/org/nervos/ckb/type/concrete/BlockV1.java @@ -49,6 +49,10 @@ public Bytes getExtension() { return extension; } + public Block asV0() { + return Block.Builder.buildUnchecked(this.buf); + } + public static Builder builder() { return new Builder(); } diff --git a/utils/src/test/java/org/nervos/ckb/utils/NumericTest.java b/utils/src/test/java/org/nervos/ckb/utils/NumericTest.java index dfe1aaad7..963ef5647 100644 --- a/utils/src/test/java/org/nervos/ckb/utils/NumericTest.java +++ b/utils/src/test/java/org/nervos/ckb/utils/NumericTest.java @@ -101,6 +101,10 @@ public void testToBytesPadded() { Assertions.assertArrayEquals( Numeric.toBytesPadded(BigInteger.valueOf(Integer.MAX_VALUE), 4), new byte[]{0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff}); + + Assertions.assertArrayEquals( + new byte[]{(byte)0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}, + Numeric.toBytesPadded(BigInteger.valueOf(-1), 4)); } @Test @@ -198,6 +202,16 @@ public void testIsIntegerValue2() { public void testLittleEndian() { String littleEndian = Numeric.littleEndian(71); Assertions.assertEquals("0x4700000000000000", littleEndian); + + String negLittleEndian = Numeric.littleEndian(-1); + Assertions.assertEquals("0xffffffffffffffff", negLittleEndian); + String negLittleEndian2= Numeric.littleEndian(-2); + Assertions.assertEquals("0xfeffffffffffffff", negLittleEndian2); + + long v = 0x7eadbeef; + String negBeef = Numeric.littleEndian(-v); + // 7e => 81, ad => 52, be => 41, ef=> 11 + Assertions.assertEquals("0x11415281ffffffff", negBeef); } @Test From 02ee2747fb2bda0fddffd77bc163092ae4036122 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Thu, 2 Feb 2023 21:35:00 +0800 Subject: [PATCH 07/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Support=20packed?= =?UTF-8?q?=20header=20RPC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit support getPackedTipHeader/getPackedHeader/getPackedHeaderByNumber --- .../main/java/org/nervos/ckb/CkbRpcApi.java | 3 +++ .../main/java/org/nervos/ckb/service/Api.java | 27 ++++++++++++++++++- ckb/src/test/java/service/ApiTest.java | 17 ++++++++++++ .../org/nervos/ckb/type/PackedHeader.java | 19 +++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/nervos/ckb/type/PackedHeader.java diff --git a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java index ee0535939..700b4d08e 100644 --- a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java +++ b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java @@ -25,6 +25,7 @@ public interface CkbRpcApi { BlockEconomicState getBlockEconomicState(byte[] blockHash) throws IOException; Header getTipHeader() throws IOException; + PackedHeader getPackedTipHeader() throws IOException; CellWithStatus getLiveCell(OutPoint outPoint, boolean withData) throws IOException; @@ -35,8 +36,10 @@ public interface CkbRpcApi { Epoch getEpochByNumber(long epochNumber) throws IOException; Header getHeader(byte[] blockHash) throws IOException; + PackedHeader getPackedHeader(byte[] blockHash) throws IOException; Header getHeaderByNumber(long blockNumber) throws IOException; + PackedHeader getPackedHeaderByNumber(long blockNumber) throws IOException; TransactionProof getTransactionProof(List txHashes) throws IOException; diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index 6bc1068ea..fa6c04459 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -65,7 +65,7 @@ public BlockWithCycles getBlockByNumber(long blockNumber, boolean with_cycles) t return ret; } } - + @Override public PackedBlockWithCycles getPackedBlock(byte[] blockHash, boolean with_cycles) throws IOException { if (with_cycles) { @@ -118,6 +118,14 @@ public Header getTipHeader() throws IOException { return rpcService.post("get_tip_header", Collections.emptyList(), Header.class); } + @Override + public PackedHeader getPackedTipHeader() throws IOException { + String s = rpcService.post("get_tip_header", Collections.singletonList(0), String.class); + PackedHeader ret = new PackedHeader(); + ret.header = s; + return ret; + } + @Override public CellWithStatus getLiveCell(OutPoint outPoint, boolean withData) throws IOException { return rpcService.post( @@ -148,12 +156,29 @@ public Header getHeader(byte[] blockHash) throws IOException { return rpcService.post("get_header", Collections.singletonList(blockHash), Header.class); } + @Override + public PackedHeader getPackedHeader(byte[] blockHash) throws IOException { + String s = rpcService.post("get_header", Arrays.asList(blockHash, 0), String.class); + PackedHeader ret = new PackedHeader(); + ret.header = s; + return ret; + } + @Override public Header getHeaderByNumber(long blockNumber) throws IOException { return rpcService.post( "get_header_by_number", Collections.singletonList(blockNumber), Header.class); } + @Override + public PackedHeader getPackedHeaderByNumber(long blockNumber) throws IOException { + String s = rpcService.post( + "get_header_by_number", Arrays.asList(blockNumber, 0), String.class); + PackedHeader ret = new PackedHeader(); + ret.header = s; + return ret; + } + @Override public TransactionProof getTransactionProof(List txHashes) throws IOException { return rpcService.post( diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index 32befbade..e809d7094 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -154,6 +154,17 @@ public void testGetTipHeader() throws IOException { Assertions.assertNotEquals(0, header.compactTarget); } + @Test + public void testGetPackedTipHeader() throws IOException { + PackedHeader tipHeader = api.getPackedTipHeader(); + + org.nervos.ckb.type.concrete.Header h = org.nervos.ckb.type.concrete.Header.builder(tipHeader.getHeaderBytes()).build(); + + byte[] headerHash = tipHeader.calculateHash(); + PackedHeader packedHeader = api.getPackedHeader(headerHash); + Assertions.assertEquals(tipHeader.header, packedHeader.header); + } + @Test public void testGetTipBlockNumber() throws IOException { long blockNumber = api.getTipBlockNumber(); @@ -182,6 +193,9 @@ public void testGetHeader() throws IOException { Header header = api.getHeader(blockHash); Assertions.assertEquals(1, header.number); Assertions.assertEquals(1590137711584L, header.timestamp); + + PackedHeader packedHeader = api.getPackedHeader(blockHash); + Assertions.assertArrayEquals(header.pack().toByteArray(), packedHeader.getHeaderBytes()); } @Test @@ -189,6 +203,9 @@ public void testGetHeaderByNumber() throws IOException { Header header = api.getHeaderByNumber(1); Assertions.assertEquals(1, header.number); Assertions.assertEquals(1590137711584L, header.timestamp); + + PackedHeader packedHeader = api.getPackedHeaderByNumber(1); + Assertions.assertArrayEquals(header.pack().toByteArray(), packedHeader.getHeaderBytes()); } @Test diff --git a/core/src/main/java/org/nervos/ckb/type/PackedHeader.java b/core/src/main/java/org/nervos/ckb/type/PackedHeader.java new file mode 100644 index 000000000..3a993b111 --- /dev/null +++ b/core/src/main/java/org/nervos/ckb/type/PackedHeader.java @@ -0,0 +1,19 @@ +package org.nervos.ckb.type; + +import org.nervos.ckb.crypto.Blake2b; +import org.nervos.ckb.utils.Numeric; + +public class PackedHeader { + /** + * 0x-prefixed hex string + */ + public String header; + + public byte[] getHeaderBytes() { + return Numeric.hexStringToByteArray(this.header); + } + + public byte[] calculateHash() { + return Blake2b.digest(this.getHeaderBytes()); + } +} From 2f36ad13c2019cdf4f667d24bcc1e7c918c747c7 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Thu, 2 Feb 2023 22:02:15 +0800 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20support=20packed?= =?UTF-8?q?=20get=5Ffork=5Fblock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java | 1 + ckb/src/main/java/org/nervos/ckb/service/Api.java | 9 +++++++++ ckb/src/test/java/service/ApiTest.java | 12 ++++++++---- .../org/nervos/ckb/type/PackedBlockWithCycles.java | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java index 700b4d08e..9060d1b37 100644 --- a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java +++ b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java @@ -48,6 +48,7 @@ public interface CkbRpcApi { List verifyTransactionProof(TransactionProof transactionProof) throws IOException; Block getForkBlock(byte[] blockHash) throws IOException; + PackedBlockWithCycles getPackedForkBlock(byte[] blockHash) throws IOException; Consensus getConsensus() throws IOException; diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index fa6c04459..e1cc1049b 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -205,6 +205,15 @@ public Block getForkBlock(byte[] blockHash) throws IOException { return rpcService.post("get_fork_block", Collections.singletonList(blockHash), Block.class); } + @Override + public PackedBlockWithCycles getPackedForkBlock(byte[] blockHash) throws IOException { + String s = rpcService.post("get_fork_block", Arrays.asList(blockHash, 0), String.class); + if (s == null) return null; + PackedBlockWithCycles ret = new PackedBlockWithCycles(); + ret.block = s; + return ret; + } + @Override public Consensus getConsensus() throws IOException { return rpcService.post("get_consensus", Collections.emptyList(), Consensus.class); diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index e809d7094..51eb75477 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -241,10 +241,14 @@ public void testGetTransactionProof() throws IOException { @Test public void testGetForkBlock() throws IOException { - Block forkBlock = - api.getForkBlock( - Numeric.hexStringToByteArray( - "0xd5ac7cf8c34a975bf258a34f1c2507638487ab71aa4d10a9ec73704aa3abf9cd")); + byte[] block_hash = Numeric.hexStringToByteArray( + "0xd5ac7cf8c34a975bf258a34f1c2507638487ab71aa4d10a9ec73704aa3abf9cd"); + Block forkBlock = api.getForkBlock(block_hash); + + PackedBlockWithCycles packedForkBlock = api.getPackedForkBlock(block_hash); + if (packedForkBlock != null) { + Assertions.assertArrayEquals(packedForkBlock.getBlockBytes(), forkBlock.pack().toByteArray()); + } } @Test diff --git a/core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java b/core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java index d788896f5..985f5e5a2 100644 --- a/core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java +++ b/core/src/main/java/org/nervos/ckb/type/PackedBlockWithCycles.java @@ -20,6 +20,6 @@ public class PackedBlockWithCycles { * @return parsed bytes from block string */ public byte[] getBlockBytes() { - return Numeric.hexStringToByteArray(this.block); + return this.block == null ? null : Numeric.hexStringToByteArray(this.block); } } From d3de6a5f0f19edd46803a0ae0ecb0bf529b1b159 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Thu, 2 Feb 2023 22:33:39 +0800 Subject: [PATCH 09/14] =?UTF-8?q?test:=20=F0=9F=92=8D=20Add=20test=20about?= =?UTF-8?q?=20not=20data=20for=20RPC=20call?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/nervos/ckb/service/Api.java | 6 ++ ckb/src/test/java/service/ApiTest.java | 69 +++++++++++++++++++ .../org/nervos/ckb/type/PackedHeader.java | 4 +- .../ckb/type/PackedTransactionWithStatus.java | 2 +- 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index e1cc1049b..d965d55f3 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -60,6 +60,7 @@ public BlockWithCycles getBlockByNumber(long blockNumber, boolean with_cycles) t return rpcService.post("get_block_by_number", params, BlockWithCycles.class); } else { Block block = rpcService.post("get_block_by_number", params, Block.class); + if (block == null) return null; BlockWithCycles ret = new BlockWithCycles(); ret.block = block; return ret; @@ -72,6 +73,7 @@ public PackedBlockWithCycles getPackedBlock(byte[] blockHash, boolean with_cycle return rpcService.post("get_block", Arrays.asList(blockHash, 0, true), PackedBlockWithCycles.class); } else { String s = rpcService.post("get_block", Arrays.asList(blockHash, 0, false), String.class); + if (s == null) return null; PackedBlockWithCycles ret = new PackedBlockWithCycles(); ret.block = s; return ret; @@ -85,6 +87,7 @@ public PackedBlockWithCycles getPackedBlockByNumber(long blockNumber, boolean wi return rpcService.post("get_block_by_number", params, PackedBlockWithCycles.class); } else { String s = rpcService.post("get_block_by_number", params, String.class); + if (s == null) return null; PackedBlockWithCycles ret = new PackedBlockWithCycles(); ret.block = s; return ret; @@ -121,6 +124,7 @@ public Header getTipHeader() throws IOException { @Override public PackedHeader getPackedTipHeader() throws IOException { String s = rpcService.post("get_tip_header", Collections.singletonList(0), String.class); + if (s == null) return null; PackedHeader ret = new PackedHeader(); ret.header = s; return ret; @@ -159,6 +163,7 @@ public Header getHeader(byte[] blockHash) throws IOException { @Override public PackedHeader getPackedHeader(byte[] blockHash) throws IOException { String s = rpcService.post("get_header", Arrays.asList(blockHash, 0), String.class); + if (s == null) return null; PackedHeader ret = new PackedHeader(); ret.header = s; return ret; @@ -174,6 +179,7 @@ public Header getHeaderByNumber(long blockNumber) throws IOException { public PackedHeader getPackedHeaderByNumber(long blockNumber) throws IOException { String s = rpcService.post( "get_header_by_number", Arrays.asList(blockNumber, 0), String.class); + if (s == null) return null; PackedHeader ret = new PackedHeader(); ret.header = s; return ret; diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index 51eb75477..749318b36 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -19,6 +19,11 @@ @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ApiTest { + // python code: "block_hash_that_does_not_exist".encode("utf-8").hex() + // output '626c6f636b5f686173685f746861745f646f65735f6e6f745f6578697374' + byte[] BLOCK_HASH_NOT_EXIST = Numeric.hexStringToByteArray( + "0x626c6f636b5f686173685f746861745f646f65735f6e6f745f65786973740000"); + long block_number_not_exist = 0xffffffffffffffffL; private Api api; @@ -53,7 +58,21 @@ public void testGetBlockByNumberWithCycles() throws IOException { Assertions.assertArrayEquals(packedResponse.getBlockBytes(), packedResponse0.getBlockBytes()); Assertions.assertNull(packedResponse0.cycles); } + @Test + public void testGetBlockByNumberWithCycles_NotExist() throws IOException { + long blockNumber = block_number_not_exist; + BlockWithCycles response = api.getBlockByNumber(blockNumber, true); + Assertions.assertNull(response); + BlockWithCycles response0 = api.getBlockByNumber(blockNumber, false); + Assertions.assertNull(response0); + + PackedBlockWithCycles packedResponse = api.getPackedBlockByNumber(blockNumber, true); + Assertions.assertNull(packedResponse); + + PackedBlockWithCycles packedResponse0 = api.getPackedBlockByNumber(blockNumber, false); + Assertions.assertNull(packedResponse0); + } @Test public void testGetBlockHashByNumber() throws IOException { @@ -99,6 +118,18 @@ public void testGetBlock() throws IOException { Assertions.assertArrayEquals(bytes, bytes_from_json); } + @Test + public void testGetPackedBlock_NotExist() throws IOException { + byte[] blockHash = BLOCK_HASH_NOT_EXIST; + Block block = api.getBlock(blockHash); + Assertions.assertNull(block); + + PackedBlockWithCycles packedBlockBytes = api.getPackedBlock(blockHash, true); + Assertions.assertNull(packedBlockBytes); + + PackedBlockWithCycles packedBlockBytes0 = api.getPackedBlock(blockHash, false); + Assertions.assertNull(packedBlockBytes0); + } @Test public void testGetBlockWithCycles() throws IOException { byte[] blockHash = @@ -147,6 +178,16 @@ public void testPackedTransaction() throws IOException { Assertions.assertArrayEquals(bytes_from_json, transaction_bytes); } + @Test + public void testPackedTransactionNotExist() throws IOException { + byte[] transactionHash = BLOCK_HASH_NOT_EXIST; + PackedTransactionWithStatus packedTransaction = api.getPackedTransaction(transactionHash); + Assertions.assertEquals(TransactionWithStatus.Status.UNKNOWN, packedTransaction.txStatus.status); + + TransactionWithStatus transaction = api.getTransaction(transactionHash); + Assertions.assertEquals(TransactionWithStatus.Status.UNKNOWN, transaction.txStatus.status); + } + @Test public void testGetTipHeader() throws IOException { Header header = api.getTipHeader(); @@ -198,6 +239,16 @@ public void testGetHeader() throws IOException { Assertions.assertArrayEquals(header.pack().toByteArray(), packedHeader.getHeaderBytes()); } + @Test + public void testGetHeader_NotExist() throws IOException { + byte[] blockHash = BLOCK_HASH_NOT_EXIST; + Header header = api.getHeader(blockHash); + Assertions.assertNull(header); + + PackedHeader packedHeader = api.getPackedHeader(blockHash); + Assertions.assertNull(packedHeader); + } + @Test public void testGetHeaderByNumber() throws IOException { Header header = api.getHeaderByNumber(1); @@ -208,6 +259,14 @@ public void testGetHeaderByNumber() throws IOException { Assertions.assertArrayEquals(header.pack().toByteArray(), packedHeader.getHeaderBytes()); } + @Test + public void testGetHeaderByNumber_NotExist() throws IOException { + Header header = api.getHeaderByNumber(block_number_not_exist); + Assertions.assertNull(header); + + PackedHeader packedHeader = api.getPackedHeaderByNumber(block_number_not_exist); + Assertions.assertNull(packedHeader); + } @Test public void testGetConsensus() throws IOException { Consensus consensus = api.getConsensus(); @@ -251,6 +310,16 @@ public void testGetForkBlock() throws IOException { } } + @Test + public void testGetForkBlock_NotExist() throws IOException { + byte[] block_hash = BLOCK_HASH_NOT_EXIST; + Block forkBlock = api.getForkBlock(block_hash); + Assertions.assertNull(forkBlock); + + PackedBlockWithCycles packedForkBlock = api.getPackedForkBlock(block_hash); + Assertions.assertNull(packedForkBlock); + } + @Test public void testLocalNodeInfo() throws IOException { NodeInfo nodeInfo = api.localNodeInfo(); diff --git a/core/src/main/java/org/nervos/ckb/type/PackedHeader.java b/core/src/main/java/org/nervos/ckb/type/PackedHeader.java index 3a993b111..d8556f427 100644 --- a/core/src/main/java/org/nervos/ckb/type/PackedHeader.java +++ b/core/src/main/java/org/nervos/ckb/type/PackedHeader.java @@ -10,10 +10,10 @@ public class PackedHeader { public String header; public byte[] getHeaderBytes() { - return Numeric.hexStringToByteArray(this.header); + return header == null ? null : Numeric.hexStringToByteArray(this.header); } public byte[] calculateHash() { - return Blake2b.digest(this.getHeaderBytes()); + return header == null ? null : Blake2b.digest(this.getHeaderBytes()); } } diff --git a/core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java b/core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java index 86f6ba1c3..3654751a1 100644 --- a/core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java +++ b/core/src/main/java/org/nervos/ckb/type/PackedTransactionWithStatus.java @@ -11,6 +11,6 @@ public class PackedTransactionWithStatus { * @return parsed bytes from transaction string */ public byte[] getTransactionBytes() { - return Numeric.hexStringToByteArray(this.transaction); + return this.transaction == null ? null : Numeric.hexStringToByteArray(this.transaction); } } From 4c5c5c82be2a9b55079ab7376a34f84652520ed8 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Thu, 2 Feb 2023 22:51:32 +0800 Subject: [PATCH 10/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20get=5Ftransa?= =?UTF-8?q?ction=20with=20verbosity=3D1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/nervos/ckb/CkbRpcApi.java | 8 +++++++ .../main/java/org/nervos/ckb/service/Api.java | 5 +++++ ckb/src/test/java/service/ApiTest.java | 22 +++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java index 9060d1b37..d11d504b9 100644 --- a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java +++ b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java @@ -19,6 +19,14 @@ public interface CkbRpcApi { PackedBlockWithCycles getPackedBlockByNumber(long blockNumber, boolean with_cycles) throws IOException; TransactionWithStatus getTransaction(byte[] transactionHash) throws IOException; + + /** + * get transaction with verbosity value is 1 + * @param transactionHash the transaction hash + * @return he RPC does not return the transaction content and the field transaction must be null. + * @throws IOException + */ + TransactionWithStatus getTransactionVerbosity1(byte[] transactionHash) throws IOException; PackedTransactionWithStatus getPackedTransaction(byte[] transactionHash) throws IOException; byte[] getBlockHash(long blockNumber) throws IOException; diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index d965d55f3..916399cac 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -100,6 +100,11 @@ public TransactionWithStatus getTransaction(byte[] transactionHash) throws IOExc "get_transaction", Collections.singletonList(transactionHash), TransactionWithStatus.class); } + @Override + public TransactionWithStatus getTransactionVerbosity1(byte[] transactionHash) throws IOException { + return rpcService.post("get_transaction", Arrays.asList(transactionHash, 1), TransactionWithStatus.class); + } + @Override public PackedTransactionWithStatus getPackedTransaction(byte[] transactionHash) throws IOException { return rpcService.post("get_transaction", Arrays.asList(transactionHash, 0), PackedTransactionWithStatus.class); diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index 749318b36..fb6852a7b 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -166,6 +166,28 @@ public void testTransaction() throws IOException { Assertions.assertTrue(transactionWithStatus.cycles > 0); } + @Test + public void testGetTransactionVerbosity1() throws IOException { + byte[] transactionHash = + Numeric.hexStringToByteArray( + "0x8277d74d33850581f8d843613ded0c2a1722dec0e87e748f45c115dfb14210f1"); + TransactionWithStatus transactionVerbosity1 = api.getTransactionVerbosity1(transactionHash); + Assertions.assertNull(transactionVerbosity1.transaction); + + TransactionWithStatus transactionVerbosity2 = api.getTransaction(transactionHash); + Assertions.assertEquals(transactionVerbosity1.txStatus.status, transactionVerbosity2.txStatus.status); + Assertions.assertArrayEquals(transactionVerbosity1.txStatus.blockHash, transactionVerbosity2.txStatus.blockHash); + Assertions.assertEquals(transactionVerbosity1.cycles, transactionVerbosity2.cycles); + } + @Test + public void testGetTransactionVerbosity1_NotExist() throws IOException { + byte[] transactionHash = BLOCK_HASH_NOT_EXIST; + TransactionWithStatus transactionVerbosity1 = api.getTransactionVerbosity1(transactionHash); + Assertions.assertEquals(TransactionWithStatus.Status.UNKNOWN, transactionVerbosity1.txStatus.status); + + TransactionWithStatus transactionVerbosity2 = api.getTransaction(transactionHash); + Assertions.assertEquals(TransactionWithStatus.Status.UNKNOWN, transactionVerbosity1.txStatus.status); + } @Test public void testPackedTransaction() throws IOException { byte[] transactionHash = From 83bb03745618e784fa5d758997b4ab12a73dd641 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Mon, 6 Feb 2023 10:11:19 +0800 Subject: [PATCH 11/14] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20getTransaction?= =?UTF-8?q?Verbosity1=20=3D>=20getTransactionStatus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename getTransactionVerbosity1 to getTransactionStatus to get only txStatus and cycles without transaction content. --- ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java | 4 ++-- ckb/src/main/java/org/nervos/ckb/service/Api.java | 2 +- ckb/src/test/java/service/ApiTest.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java index d11d504b9..8eca09526 100644 --- a/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java +++ b/ckb/src/main/java/org/nervos/ckb/CkbRpcApi.java @@ -23,10 +23,10 @@ public interface CkbRpcApi { /** * get transaction with verbosity value is 1 * @param transactionHash the transaction hash - * @return he RPC does not return the transaction content and the field transaction must be null. + * @return the RPC does not return the transaction content and the field transaction must be null. * @throws IOException */ - TransactionWithStatus getTransactionVerbosity1(byte[] transactionHash) throws IOException; + TransactionWithStatus getTransactionStatus(byte[] transactionHash) throws IOException; PackedTransactionWithStatus getPackedTransaction(byte[] transactionHash) throws IOException; byte[] getBlockHash(long blockNumber) throws IOException; diff --git a/ckb/src/main/java/org/nervos/ckb/service/Api.java b/ckb/src/main/java/org/nervos/ckb/service/Api.java index 916399cac..20c58b257 100644 --- a/ckb/src/main/java/org/nervos/ckb/service/Api.java +++ b/ckb/src/main/java/org/nervos/ckb/service/Api.java @@ -101,7 +101,7 @@ public TransactionWithStatus getTransaction(byte[] transactionHash) throws IOExc } @Override - public TransactionWithStatus getTransactionVerbosity1(byte[] transactionHash) throws IOException { + public TransactionWithStatus getTransactionStatus(byte[] transactionHash) throws IOException { return rpcService.post("get_transaction", Arrays.asList(transactionHash, 1), TransactionWithStatus.class); } diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index fb6852a7b..0a34eab57 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -171,7 +171,7 @@ public void testGetTransactionVerbosity1() throws IOException { byte[] transactionHash = Numeric.hexStringToByteArray( "0x8277d74d33850581f8d843613ded0c2a1722dec0e87e748f45c115dfb14210f1"); - TransactionWithStatus transactionVerbosity1 = api.getTransactionVerbosity1(transactionHash); + TransactionWithStatus transactionVerbosity1 = api.getTransactionStatus(transactionHash); Assertions.assertNull(transactionVerbosity1.transaction); TransactionWithStatus transactionVerbosity2 = api.getTransaction(transactionHash); @@ -182,7 +182,7 @@ public void testGetTransactionVerbosity1() throws IOException { @Test public void testGetTransactionVerbosity1_NotExist() throws IOException { byte[] transactionHash = BLOCK_HASH_NOT_EXIST; - TransactionWithStatus transactionVerbosity1 = api.getTransactionVerbosity1(transactionHash); + TransactionWithStatus transactionVerbosity1 = api.getTransactionStatus(transactionHash); Assertions.assertEquals(TransactionWithStatus.Status.UNKNOWN, transactionVerbosity1.txStatus.status); TransactionWithStatus transactionVerbosity2 = api.getTransaction(transactionHash); From 39e1010b0be0b8476e7bf2bd8d68a21012120423 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Sun, 12 Mar 2023 22:53:53 +0800 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20support=20indexer?= =?UTF-8?q?=20search=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 + .../indexer/model/ScriptSearchMode.java | 13 +++++ .../org/nervos/indexer/model/SearchKey.java | 8 +++ .../indexer/model/SearchKeyBuilder.java | 35 ++++++++++--- ckb/src/test/java/service/ApiTest.java | 51 ++++++++++++++++++- .../org/nervos/ckb/service/RpcService.java | 3 +- 6 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 ckb-indexer/src/main/java/org/nervos/indexer/model/ScriptSearchMode.java diff --git a/CHANGELOG.md b/CHANGELOG.md index e25a99086..a689e430a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # 2.1.1 (2023-01-16) - feat: support with_cycles for get_block and get_block_by_number rpc +- feat: support packed rpcs +- feat: support indexer exact search mod ## 🚀 Features # 2.1.0 (2022-12-26) diff --git a/ckb-indexer/src/main/java/org/nervos/indexer/model/ScriptSearchMode.java b/ckb-indexer/src/main/java/org/nervos/indexer/model/ScriptSearchMode.java new file mode 100644 index 000000000..62fc1fcc6 --- /dev/null +++ b/ckb-indexer/src/main/java/org/nervos/indexer/model/ScriptSearchMode.java @@ -0,0 +1,13 @@ +package org.nervos.indexer.model; + +import com.google.gson.annotations.SerializedName; + +public enum ScriptSearchMode { + // search script with prefix + @SerializedName("prefix") + Prefix, + // search script with exact match + @SerializedName("exact") + Exact, + ; +} diff --git a/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKey.java b/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKey.java index caa7e00f8..10f4b4516 100644 --- a/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKey.java +++ b/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKey.java @@ -6,6 +6,14 @@ public class SearchKey { public Script script; public ScriptType scriptType; + /** + * Script search mode, optional default is prefix, means search script with prefix + */ + public ScriptSearchMode scriptSearchMode; public Filter filter; + /** + * bool, optional default is true, if with_data is set to false, the field of returning cell.output_data is null in the result + */ + public Boolean withData; public boolean groupByTransaction; } diff --git a/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKeyBuilder.java b/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKeyBuilder.java index 8ed1be107..473fead32 100644 --- a/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKeyBuilder.java +++ b/ckb-indexer/src/main/java/org/nervos/indexer/model/SearchKeyBuilder.java @@ -13,38 +13,58 @@ public class SearchKeyBuilder { private Filter filter; - public void script(Script script) { + public SearchKeyBuilder script(Script script) { this.script = script; + return this; } - public void scriptType(ScriptType scriptType) { + public SearchKeyBuilder scriptType(ScriptType scriptType) { this.scriptType = scriptType; + return this; } - public void filterScript(Script script) { + public SearchKeyBuilder filterScript(Script script) { initFilter(); this.filter.script = script; + return this; } - public void filterOutputDataLenRange(int inclusive, int exclusive) { + public SearchKeyBuilder filterOutputDataLenRange(int inclusive, int exclusive) { initFilter(); this.filter.outputDataLenRange = new ArrayList<>(2); this.filter.outputDataLenRange.add(inclusive); this.filter.outputDataLenRange.add(exclusive); + return this; } - public void filterOutputCapacityRange(long inclusive, long exclusive) { + public SearchKeyBuilder filterOutputCapacityRange(long inclusive, long exclusive) { initFilter(); this.filter.outputCapacityRange = new ArrayList<>(2); this.filter.outputCapacityRange.add(inclusive); this.filter.outputCapacityRange.add(exclusive); + return this; } - public void filterBlockRange(int inclusive, int exclusive) { + public SearchKeyBuilder filterBlockRange(int inclusive, int exclusive) { initFilter(); this.filter.blockRange = new ArrayList<>(2); this.filter.blockRange.add(inclusive); this.filter.blockRange.add(exclusive); + return this; + } + + private ScriptSearchMode _scriptSearchMode; + + public SearchKeyBuilder scriptSearchMode(ScriptSearchMode scriptSearchMode) { + this._scriptSearchMode = scriptSearchMode; + return this; + } + + private Boolean _withData; + + public SearchKeyBuilder withData(Boolean withData) { + this._withData = withData; + return this; } public SearchKey build() { @@ -52,6 +72,9 @@ public SearchKey build() { searchKey.script = this.script; searchKey.scriptType = this.scriptType; searchKey.filter = this.filter; + searchKey.scriptSearchMode = this._scriptSearchMode; + searchKey.withData = this._withData; + // searchKey.groupByTransaction controlled by api function return searchKey; } diff --git a/ckb/src/test/java/service/ApiTest.java b/ckb/src/test/java/service/ApiTest.java index 0a34eab57..f00d808d1 100644 --- a/ckb/src/test/java/service/ApiTest.java +++ b/ckb/src/test/java/service/ApiTest.java @@ -8,6 +8,7 @@ import org.nervos.ckb.type.*; import org.nervos.ckb.utils.Numeric; import org.nervos.indexer.model.Order; +import org.nervos.indexer.model.ScriptSearchMode; import org.nervos.indexer.model.SearchKeyBuilder; import org.nervos.indexer.model.resp.*; @@ -58,6 +59,7 @@ public void testGetBlockByNumberWithCycles() throws IOException { Assertions.assertArrayEquals(packedResponse.getBlockBytes(), packedResponse0.getBlockBytes()); Assertions.assertNull(packedResponse0.cycles); } + @Test public void testGetBlockByNumberWithCycles_NotExist() throws IOException { long blockNumber = block_number_not_exist; @@ -130,6 +132,7 @@ public void testGetPackedBlock_NotExist() throws IOException { PackedBlockWithCycles packedBlockBytes0 = api.getPackedBlock(blockHash, false); Assertions.assertNull(packedBlockBytes0); } + @Test public void testGetBlockWithCycles() throws IOException { byte[] blockHash = @@ -179,6 +182,7 @@ public void testGetTransactionVerbosity1() throws IOException { Assertions.assertArrayEquals(transactionVerbosity1.txStatus.blockHash, transactionVerbosity2.txStatus.blockHash); Assertions.assertEquals(transactionVerbosity1.cycles, transactionVerbosity2.cycles); } + @Test public void testGetTransactionVerbosity1_NotExist() throws IOException { byte[] transactionHash = BLOCK_HASH_NOT_EXIST; @@ -188,6 +192,7 @@ public void testGetTransactionVerbosity1_NotExist() throws IOException { TransactionWithStatus transactionVerbosity2 = api.getTransaction(transactionHash); Assertions.assertEquals(TransactionWithStatus.Status.UNKNOWN, transactionVerbosity1.txStatus.status); } + @Test public void testPackedTransaction() throws IOException { byte[] transactionHash = @@ -289,6 +294,7 @@ public void testGetHeaderByNumber_NotExist() throws IOException { PackedHeader packedHeader = api.getPackedHeaderByNumber(block_number_not_exist); Assertions.assertNull(packedHeader); } + @Test public void testGetConsensus() throws IOException { Consensus consensus = api.getConsensus(); @@ -570,6 +576,49 @@ void testGetTransactions() throws IOException { Assertions.assertTrue(txs.objects.size() > 0); } + @Test + void testGetTransactions_prefix_partial() throws IOException { + SearchKeyBuilder key = new SearchKeyBuilder(); + key.script( + new Script( + Numeric.hexStringToByteArray( + "0x58c5f491aba6d61678b7cf7edf4910b1f5e00ec0cde2f42e0abb4fd9aff25a63"), + Numeric.hexStringToByteArray("0xe53f35ccf63bb37a3bb0ac3b7f89808077a78eae".substring(0, 4)), + Script.HashType.TYPE)); + key.scriptType(ScriptType.LOCK); + key.scriptSearchMode(ScriptSearchMode.Prefix); + TxsWithCell txs = api.getTransactions(key.build(), Order.ASC, 10, null); + Assertions.assertTrue(txs.objects.size() > 0); + } + + @Test + void testGetTransactions_exact_partial() throws IOException { + SearchKeyBuilder key = new SearchKeyBuilder(); + key.script( + new Script( + Numeric.hexStringToByteArray( + "0x58c5f491aba6d61678b7cf7edf4910b1f5e00ec0cde2f42e0abb4fd9aff25a63"), + Numeric.hexStringToByteArray("0xe53f35ccf63bb37a3bb0ac3b7f89808077a78eae".substring(0, 4)), + Script.HashType.TYPE)); + key.scriptType(ScriptType.LOCK).scriptSearchMode(ScriptSearchMode.Exact); + TxsWithCell txs = api.getTransactions(key.build(), Order.ASC, 10, null); + Assertions.assertEquals(0, txs.objects.size()); + } + + @Test + void testGetTransactions_exact_full() throws IOException { + SearchKeyBuilder key = new SearchKeyBuilder(); + key.script( + new Script( + Numeric.hexStringToByteArray( + "0x58c5f491aba6d61678b7cf7edf4910b1f5e00ec0cde2f42e0abb4fd9aff25a63"), + Numeric.hexStringToByteArray("0xe53f35ccf63bb37a3bb0ac3b7f89808077a78eae"), + Script.HashType.TYPE)); + key.scriptType(ScriptType.LOCK).scriptSearchMode(ScriptSearchMode.Exact); + TxsWithCell txs = api.getTransactions(key.build(), Order.ASC, 10, null); + Assertions.assertTrue(txs.objects.size() > 0); + } + @Test void testTransactionsGrouped() throws IOException { SearchKeyBuilder key = new SearchKeyBuilder(); @@ -705,7 +754,5 @@ public void testGetFeeRateStatics() throws IOException { statics = api.getFeeRateStatics(102); Assertions.assertNotNull(statics); Assertions.assertTrue(statics.mean > 0 && statics.median > 0); - - Assertions.assertThrows(IOException.class, () -> api.getFeeRateStatics(-1)); } } diff --git a/core/src/main/java/org/nervos/ckb/service/RpcService.java b/core/src/main/java/org/nervos/ckb/service/RpcService.java index 445ff6e8d..f52f8aa70 100644 --- a/core/src/main/java/org/nervos/ckb/service/RpcService.java +++ b/core/src/main/java/org/nervos/ckb/service/RpcService.java @@ -51,7 +51,8 @@ public T post(@NotNull String method, List params, Type cls) throws IOExcept public T post(@NotNull String method, List params, Type cls, Gson gson) throws IOException { RequestParams requestParams = new RequestParams(method, params); - RequestBody body = RequestBody.create(gson.toJson(requestParams), JSON_MEDIA_TYPE); + String gson_params = gson.toJson(requestParams); + RequestBody body = RequestBody.create(gson_params, JSON_MEDIA_TYPE); Request request = new Request.Builder().url(url).post(body).build(); Response response = client.newCall(request).execute(); String responseBody = Objects.requireNonNull(response.body()).string(); From eb762b54cf77294b140164e938cd8db78e29da18 Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Wed, 22 Mar 2023 10:42:27 +0800 Subject: [PATCH 13/14] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20Update=20CHA?= =?UTF-8?q?NGELOG.md=20to=20prepare=20new=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a689e430a..4f68c1369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ -# 2.1.1 (2023-01-16) -- feat: support with_cycles for get_block and get_block_by_number rpc -- feat: support packed rpcs -- feat: support indexer exact search mod +# 2.1.1 (2023-03-23) +- feat: support with_cycles for get_block and get_block_by_number rpc (#623) +- feat: support packed rpcs (#624) +- feat: support indexer exact search mod (#627) ## 🚀 Features # 2.1.0 (2022-12-26) From b8a55db0f78966bbe6f86c23ae7f44e36d905e0b Mon Sep 17 00:00:00 2001 From: Liu Chuankai Date: Thu, 23 Mar 2023 09:58:28 +0800 Subject: [PATCH 14/14] =?UTF-8?q?chore:=20=F0=9F=A4=96=20change=20version?= =?UTF-8?q?=20to=202.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- light-client/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f32ec82fe..5e7dbd9b1 100644 --- a/build.gradle +++ b/build.gradle @@ -97,7 +97,7 @@ configure(subprojects.findAll { it.name != 'tests' }) { publications { mavenJava(MavenPublication) { groupId 'org.nervos.ckb' - version '2.1.0' + version '2.1.1' from components.java } } diff --git a/light-client/build.gradle b/light-client/build.gradle index 04c688523..affbfdeff 100644 --- a/light-client/build.gradle +++ b/light-client/build.gradle @@ -3,7 +3,7 @@ plugins { } group 'org.nervos.ckb' -version '2.1.0' +version '2.1.1' repositories { mavenCentral()