-# tx_signer\r
-\r
-Java implementation of signing transaction offline to bytomd and serializing transaction to submit.\r
-\r
-## Pre\r
-\r
-#### Get the source code\r
-\r
-```\r
-$ git clone https://github.com/Bytom/bytom.git $GOPATH/src/github.com/bytom\r
-```\r
-\r
-#### git checkout\r
-\r
-```\r
-$ git checkout dev\r
-```\r
-\r
-**Why need dev branch? Because you could call decode transaction api from dev branch and obtain tx_id and some inputs ids.**\r
-\r
-#### Build\r
-\r
-```\r
-$ cd $GOPATH/src/github.com/bytom\r
-$ make bytomd # build bytomd\r
-$ make bytomcli # build bytomcli\r
-```\r
-\r
-When successfully building the project, the `bytom` and `bytomcli` binary should be present in `cmd/bytomd` and `cmd/bytomcli` directory, respectively.\r
-\r
-#### Initialize\r
-\r
-First of all, initialize the node:\r
-\r
-```\r
-$ cd ./cmd/bytomd\r
-$ ./bytomd init --chain_id solonet\r
-```\r
-\r
-#### launch\r
-\r
-```\r
-$ ./bytomd node --mining\r
-```\r
-\r
-## Usage\r
-\r
-#### Build jar\r
-\r
-1. first get source code\r
-\r
- ```\r
- git clone https://github.com/Bytom/bytom-java-sdk.git\r
- ```\r
-\r
-2. get jar package\r
-\r
- ```\r
- $ mvn assembly:assembly -Dmaven.test.skip=true\r
- ```\r
-\r
- You can get a jar with dependencies, and you can use it in your project.\r
-\r
-#### Test cases\r
-\r
-Need 3 Parameters:\r
-\r
-- Private Keys Array\r
-- UTXO list.\r
-- Submit Transaction\r
- - call submit-transaction api. [submit-transaction api](https://github.com/Bytom/bytom/wiki/API-Reference#submit-transaction)\r
\r
\r
+# tx_signer \r
+ \r
+Java implementation of signing transaction offline to bytomd and serializing transaction to submit. \r
+ \r
+## Pre \r
+ \r
+#### Get the source code \r
+ \r
+``` \r
+$ git clone https://github.com/Bytom/bytom.git $GOPATH/src/github.com/bytom \r
+``` \r
+ \r
+#### git checkout \r
+ \r
+``` \r
+$ git checkout dev \r
+``` \r
+ \r
+**Why need dev branch? Because you could call decode transaction api from dev branch and obtain tx_id and some inputs ids.** \r
+ \r
+#### Build \r
+ \r
+``` \r
+$ cd $GOPATH/src/github.com/bytom \r
+$ make bytomd # build bytomd \r
+$ make bytomcli # build bytomcli \r
+``` \r
+ \r
+When successfully building the project, the `bytom` and `bytomcli` binary should be present in `cmd/bytomd` and `cmd/bytomcli` directory, respectively. \r
+ \r
+#### Initialize \r
+ \r
+First of all, initialize the node: \r
+ \r
+``` \r
+$ cd ./cmd/bytomd \r
+$ ./bytomd init --chain_id solonet \r
+``` \r
+ \r
+#### launch \r
+ \r
+``` \r
+$ ./bytomd node --mining \r
+``` \r
+ \r
+## Usage \r
+ \r
+#### Build jar \r
+ \r
+1. first get source code \r
+ \r
+ ``` \r
+ git clone https://github.com/Bytom/bytom-java-sdk.git \r
+ ``` \r
+ \r
+2. get jar package \r
+ \r
+ ``` \r
+ $ mvn assembly:assembly -Dmaven.test.skip=true \r
+ ``` \r
+ \r
+ You can get a jar with dependencies, and you can use it in your project. \r
+ \r
+#### Test cases \r
+ \r
+Need 3 Parameters: \r
+ \r
+- Private Keys Array \r
+- UTXO list. \r
+- Submit Transaction \r
+ - call submit-transaction api. [submit-transaction api](https://github.com/Bytom/bytom/wiki/API-Reference#submit-transaction) \r
+ \r
+ \r
\r
```java\r
\r
-//utxo json to input public Transaction.AnnotatedInput btmUtxoToInput() {\r
- String utxoJson = "{\n" +\r
- " \"id\": \"cf2f5c7340490d33d535a680dc8d95bb66fcccbf1045706484621cc067b982ae\",\n" +\r
- " \"amount\": 70000000,\n" +\r
- " \"address\": \"tm1qf4g97wae3fsz973huwrjqnd68v530nmd7n2pc43zfpw9tvd30qfsd7jl8p\",\n" +\r
- " \"program\": \"00204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813\",\n" +\r
- " \"change\": false,\n" +\r
- " \"highest\": 140925,\n" +\r
- " \"account_alias\": \"mutiaccout\",\n" +\r
- " \"asset_id\": \"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n" +\r
- " \"asset_alias\": \"BTM\",\n" +\r
- " \"account_id\": \"0PCB0S1GG0A02\",\n" +\r
- " \"control_program_index\": 2,\n" +\r
- " \"source_id\": \"9b29c72a653f986d5c5a7bf16c0fe63a9f639a0d15f3faeabeb4c14df70bbd91\",\n" +\r
- " \"source_pos\": 0,\n" +\r
- " \"valid_height\": 0,\n" +\r
- " \"derive_rule\": 0\n" +\r
- "}";\r
- UTXO utxo = UTXO.fromJson(utxoJson);\r
- Transaction.AnnotatedInput input = UTXO.utxoToAnnotatedInput(utxo);\r
- return input;\r
+//utxo json to input public Transaction.AnnotatedInput btmUtxoToInput() { \r
+ String utxoJson = "{\n" + \r
+ " \"id\": \"cf2f5c7340490d33d535a680dc8d95bb66fcccbf1045706484621cc067b982ae\",\n" + \r
+ " \"amount\": 70000000,\n" + \r
+ " \"address\": \"tm1qf4g97wae3fsz973huwrjqnd68v530nmd7n2pc43zfpw9tvd30qfsd7jl8p\",\n" + \r
+ " \"program\": \"00204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813\",\n" + \r
+ " \"change\": false,\n" + \r
+ " \"highest\": 140925,\n" + \r
+ " \"account_alias\": \"mutiaccout\",\n" + \r
+ " \"asset_id\": \"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n" + \r
+ " \"asset_alias\": \"BTM\",\n" + \r
+ " \"account_id\": \"0PCB0S1GG0A02\",\n" + \r
+ " \"control_program_index\": 2,\n" + \r
+ " \"source_id\": \"9b29c72a653f986d5c5a7bf16c0fe63a9f639a0d15f3faeabeb4c14df70bbd91\",\n" + \r
+ " \"source_pos\": 0,\n" + \r
+ " \"valid_height\": 0,\n" + \r
+ " \"derive_rule\": 0\n" + \r
+ "}"; \r
+ UTXO utxo = UTXO.fromJson(utxoJson); \r
+ Transaction.AnnotatedInput input = UTXO.utxoToAnnotatedInput(utxo); \r
+ return input; \r
}\r
\r
-```\r
-\r
-Single-key Example :\r
-\r
-```java\r
-String rootKey = "38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4";\r
-String btmAssetID = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";\r
-\r
-\r
- @Test\r
- public void testSpend() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException {\r
- Transaction.AnnotatedInput input = btmUtxoToInput();\r
- Transaction Transaction = new Transaction.Builder()\r
-// .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
-// setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0))\r
- .addInput(input.setType(1))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(170000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(10000000).setControlProgram("0020fa56ca7d47f8528e68e120d0e052885faeb9d090d238fa4266bdde21b137513c"))\r
- .build(200000);\r
- Transaction transaction = MapTransaction.mapTx(Transaction);\r
- SignTransaction signTransaction = new SignTransaction();\r
- String rawTransaction = signTransaction.rawTransaction(rootKey, transaction);\r
- System.out.println(rawTransaction);\r
- }\r
-\r
- //issue asset\r
- @Test\r
- public void testIssue() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException {\r
-\r
- String issueAssetId = "a680606d49daae62ef9cb03263ca82a0b1e3184bb6311ea52a5189207f718789";\r
- String program = "ae204cae24c2cec15491e70fc554026469496e373df9b9970b23acac8b782da0822d5151ad";\r
- String assetDefine = "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d";\r
- Transaction Transaction = new Transaction.Builder()\r
- .addInput(new Transaction.AnnotatedInput().setType(0).setAssetId(issueAssetId).setControlProgram(program).setAmount(100000000).setAssetDefinition(assetDefine).setChange(false).setKeyIndex(13))\r
- .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
- setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(issueAssetId).setAmount(100000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(870000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
- .build(2000000);\r
- MapTransaction.mapTx(Transaction);\r
- SignTransaction sign = new SignTransaction();\r
- String rawTransaction = sign.rawTransaction(rootKey, Transaction);\r
- System.out.println(rawTransaction);\r
- }\r
-\r
-\r
- //retire asset\r
- @Test\r
- public void testRetire() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException {\r
- String assetId1 = "8e962912423d8aea3409d1754782e7910da81b66c640aece14a6dac238f38e9b";\r
- Transaction transaction = new Transaction.Builder()\r
- .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(890000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
- setChange(false).setControlProgramIndex(2).setSourceId("6026b1acb11f3cbfb5280865ea857117a76d41ba7d60509dd358648424d8496a").setSourcePosition(0))\r
- .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(assetId1).setAmount(100000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
- setChange(false).setControlProgramIndex(2).setSourceId("d53e7ccfa06d3b27933a44e5d6e3e288edfc7e38f5396b8552ef44cf58a20347").setSourcePosition(0))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
- //arbitrary add after retire control program("6a")\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(assetId1).setAmount(100000000).setControlProgram("6a"))\r
- .build(2000000);\r
- MapTransaction.mapTx(transaction);\r
- SignTransaction sign = new SignTransaction();\r
- String rawTransaction = sign.rawTransaction(rootKey, transaction);\r
- System.out.println(rawTransaction);\r
+``` \r
+ \r
+Single-key Example : \r
+ \r
+```java \r
+String rootKey = "38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4"; \r
+String btmAssetID = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; \r
+ \r
+ \r
+ @Test \r
+ public void testSpend() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException { \r
+ Transaction.AnnotatedInput input = btmUtxoToInput(); \r
+ Transaction Transaction = new Transaction.Builder() \r
+// .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"). \r
+// setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0)) \r
+ .addInput(input.setType(1)) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(170000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b")) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(10000000).setControlProgram("0020fa56ca7d47f8528e68e120d0e052885faeb9d090d238fa4266bdde21b137513c")) \r
+ .build(200000); \r
+ Transaction transaction = MapTransaction.mapTx(Transaction); \r
+ SignTransaction signTransaction = new SignTransaction(); \r
+ String rawTransaction = signTransaction.rawTransaction(rootKey, transaction); \r
+ System.out.println(rawTransaction); \r
+ } \r
+ \r
+ //issue asset \r
+ @Test \r
+ public void testIssue() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException { \r
+ \r
+ String issueAssetId = "a680606d49daae62ef9cb03263ca82a0b1e3184bb6311ea52a5189207f718789"; \r
+ String program = "ae204cae24c2cec15491e70fc554026469496e373df9b9970b23acac8b782da0822d5151ad"; \r
+ String assetDefine = "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"; \r
+ Transaction Transaction = new Transaction.Builder() \r
+ .addInput(new Transaction.AnnotatedInput().setType(0).setAssetId(issueAssetId).setControlProgram(program).setAmount(100000000).setAssetDefinition(assetDefine).setChange(false).setKeyIndex(13)) \r
+ .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"). \r
+ setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0)) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(issueAssetId).setAmount(100000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b")) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(870000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b")) \r
+ .build(2000000); \r
+ MapTransaction.mapTx(Transaction); \r
+ SignTransaction sign = new SignTransaction(); \r
+ String rawTransaction = sign.rawTransaction(rootKey, Transaction); \r
+ System.out.println(rawTransaction); \r
+ } \r
+ \r
+ \r
+ //retire asset \r
+ @Test \r
+ public void testRetire() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException { \r
+ String arbitrary = "77656c636f6d65efbc8ce6aca2e8bf8ee69da5e588b0e58e9fe5ad90e4b896e7958c"; \r
+ String retireControlProgram = "6a"+Integer.toString(Hex.decode(arbitrary).length,16)+arbitrary; \r
+ String assetId1 = "207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf"; \r
+ \r
+ Transaction transaction = new Transaction.Builder() \r
+ .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(890000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"). \r
+ setChange(false).setControlProgramIndex(2).setSourceId("6026b1acb11f3cbfb5280865ea857117a76d41ba7d60509dd358648424d8496a").setSourcePosition(0)) \r
+ .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(assetId1).setAmount(100000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"). \r
+ setChange(false).setControlProgramIndex(2).setSourceId("d53e7ccfa06d3b27933a44e5d6e3e288edfc7e38f5396b8552ef44cf58a20347").setSourcePosition(0)) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b")) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(assetId1).setAmount(100000000).setControlProgram(retireControlProgram )) \r
+ .build(2000000); \r
+ MapTransaction.mapTx(transaction); \r
+ SignTransaction sign = new SignTransaction(); \r
+ String rawTransaction = sign.rawTransaction(rootKey, transaction); \r
+ System.out.println(rawTransaction); \r
}\r
\r
-```\r
-\r
-Multi-keys Example:\r
-\r
-> Need an account has two or more keys.\r
-\r
-```java\r
+``` \r
+ \r
+Multi-keys Example: \r
+ \r
+> Need an account has two or more keys. \r
+ \r
+```java \r
//single input and multi-sign\r
- @Test\r
- public void testMutiSpend(){\r
- Transaction.AnnotatedInput input = btmUtxoToInput();\r
- Transaction Transaction = new Transaction.Builder()\r
-// .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
-// setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0))\r
- .addInput(input.setType(1))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(50000000).setControlProgram("00204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813"))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(10000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
- .build(200000);\r
- Transaction transaction = MapTransaction.mapTx(Transaction);\r
- SignTransaction signTransaction = new SignTransaction();\r
- String[] rootKeys = new String[3];\r
- rootKeys[0] = "38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4";\r
- rootKeys[1] = "50a23bf6200b8a98afc049a7d0296a619e2ee27fa0d6d4d271ca244b280b324347627e543cc079614642c7b88c78ce38092430b01d124663e8b84026aefefde1";\r
- rootKeys[2] = "00e4bf1251fb5aa37aa2a11dec6c0db5cec3f17aa312dbddb30e06957a32ae503ebcdfd4ad5e29be21ee9ec336e939eb72439cf6d99c785268c8f3d71c1be877";\r
- signTransaction.buildWitness(transaction, 0, rootKeys);\r
- String raw = signTransaction.serializeTransaction(transaction);\r
- System.out.println(raw);\r
+ @Test \r
+ public void testMutiSpend(){ \r
+ Transaction.AnnotatedInput input = btmUtxoToInput(); \r
+ Transaction Transaction = new Transaction.Builder() \r
+// .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"). \r
+// setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0)) \r
+ .addInput(input.setType(1)) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(50000000).setControlProgram("00204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813")) \r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(10000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b")) \r
+ .build(200000); \r
+ Transaction transaction = MapTransaction.mapTx(Transaction); \r
+ SignTransaction signTransaction = new SignTransaction(); \r
+ String[] rootKeys = new String[3]; \r
+ rootKeys[0] = "38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4"; \r
+ rootKeys[1] = "50a23bf6200b8a98afc049a7d0296a619e2ee27fa0d6d4d271ca244b280b324347627e543cc079614642c7b88c78ce38092430b01d124663e8b84026aefefde1"; \r
+ rootKeys[2] = "00e4bf1251fb5aa37aa2a11dec6c0db5cec3f17aa312dbddb30e06957a32ae503ebcdfd4ad5e29be21ee9ec336e939eb72439cf6d99c785268c8f3d71c1be877"; \r
+ signTransaction.buildWitness(transaction, 0, rootKeys); \r
+ String raw = signTransaction.serializeTransaction(transaction); \r
+ System.out.println(raw); \r
}\r
```\r
\r
-Submit-transaction:\r
+Submit-transaction: \r
```java\r
-// submit rawTransaction\r
-@Test\r
-public void SubmitTransaction() throws BytomException {\r
- Client client = TestUtil.generateClient();\r
- String raw = "0701c09a0c01016b01699b29c72a653f986d5c5a7bf16c0fe63a9f639a0d15f3faeabeb4c14df70bbd91ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80bbb02100012200204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813ac020440290bc8593d429d5c7d02f96232cf8035d3776eebf2a7e855c906cdbcf35281f98575624e326fbf1f9e8de70a7047b5af2f43c1d102fcf632d1544cff46aa970540ff237b6d2c5760bf633b640e120600d06e57ab3119d192b33894967a74293531507df473235233033f12c493bc005c8d1e2f858524a431edc7d522891dfada04406ebebe5d380e129fb212a777aca0f971cfe38a2e54cd9b822459609664303aa2e10caa10f5cb8eae4a53688f895a9cbe13e5be085dd289251c63a7c86718730f67ae204e4fcad6d69dfbad1fa83c37e6fd2031476940b44a9165fa79084e5a4d9acaed20415a96ffead835222ee96eda7c16e99a4c87e8e5e43e54d2d493855f707baf78209613d3c8a4aa730bb24e0324a920b2e3c8db7260ded4527f6d6d7d14d86b64385353ad020148ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80e1eb17012200204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b1781300013cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ade2040116001414d362694eacfa110dc20dec77d610d22340f95b00";\r
- SubmitTransaction.SubmitResponse submitResponse = SubmitTransaction.submitRawTransaction(client, raw);\r
- System.out.println(submitResponse.tx_id);\r
-}
\ No newline at end of file
+// submit rawTransaction \r
+@Test \r
+public void SubmitTransaction() throws BytomException { \r
+ Client client = TestUtil.generateClient(); \r
+ String raw = "0701c09a0c01016b01699b29c72a653f986d5c5a7bf16c0fe63a9f639a0d15f3faeabeb4c14df70bbd91ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80bbb02100012200204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813ac020440290bc8593d429d5c7d02f96232cf8035d3776eebf2a7e855c906cdbcf35281f98575624e326fbf1f9e8de70a7047b5af2f43c1d102fcf632d1544cff46aa970540ff237b6d2c5760bf633b640e120600d06e57ab3119d192b33894967a74293531507df473235233033f12c493bc005c8d1e2f858524a431edc7d522891dfada04406ebebe5d380e129fb212a777aca0f971cfe38a2e54cd9b822459609664303aa2e10caa10f5cb8eae4a53688f895a9cbe13e5be085dd289251c63a7c86718730f67ae204e4fcad6d69dfbad1fa83c37e6fd2031476940b44a9165fa79084e5a4d9acaed20415a96ffead835222ee96eda7c16e99a4c87e8e5e43e54d2d493855f707baf78209613d3c8a4aa730bb24e0324a920b2e3c8db7260ded4527f6d6d7d14d86b64385353ad020148ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80e1eb17012200204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b1781300013cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ade2040116001414d362694eacfa110dc20dec77d610d22340f95b00"; \r
+ SubmitTransaction.SubmitResponse submitResponse = SubmitTransaction.submitRawTransaction(client, raw); \r
+ System.out.println(submitResponse.tx_id); \r
+}\r
* Created by liqiang on 2018/10/24.\r
*/\r
public class SignTransaction {\r
+\r
+ private final String OP_TXSIGHASH = "ae";\r
+ private final String OP_CHECKMULTISIG = "ad";\r
+\r
public String serializeTransaction(Transaction tx) {\r
String txSign = null;\r
//开始序列化\r
}\r
\r
//签名组装witness\r
- public Transaction buildWitness(Transaction transaction, int index, String priKey) {\r
+ public Transaction buildWitness(Transaction transaction, int index, byte[] privateKeyBytes) {\r
\r
Transaction.AnnotatedInput input = transaction.inputs.get(index);\r
if (null == input.witnessComponent)\r
try {\r
input.witnessComponent = new Transaction.InputWitnessComponent();\r
byte[] message = hashFn(Hex.decode(input.inputID), Hex.decode(transaction.txID));\r
- byte[] key = Hex.decode(priKey);\r
- byte[] expandedPrivateKey = ExpandedPrivateKey.ExpandedPrivateKey(key);\r
+ byte[] expandedPrivateKey = ExpandedPrivateKey.ExpandedPrivateKey(privateKeyBytes);\r
byte[] sig = Signer.Ed25519InnerSign(expandedPrivateKey, message);\r
\r
switch (input.type) {\r
case 1: {\r
input.witnessComponent.signatures = new String[2];\r
input.witnessComponent.signatures[0] = Hex.toHexString(sig);\r
- byte[] deriveXpub = DeriveXpub.deriveXpub(Hex.decode(priKey));\r
+ byte[] deriveXpub = DeriveXpub.deriveXpub(privateKeyBytes);\r
String pubKey = Hex.toHexString(deriveXpub).substring(0, 64);\r
input.witnessComponent.signatures[1] = pubKey;\r
break;\r
return transaction;\r
}\r
\r
- //多签spend\r
+ //多签单输入\r
public void buildWitness(Transaction transaction, int index, String[] privateKeys) {\r
Transaction.AnnotatedInput input = transaction.inputs.get(index);\r
if (null == input.witnessComponent)\r
try {\r
\r
//TODO 多签issue\r
- StringBuilder sb = new StringBuilder("ae");\r
+ StringBuilder sb = new StringBuilder(OP_TXSIGHASH);\r
input.witnessComponent.signatures = new String[privateKeys.length + 1];\r
for (int i = 0; i < privateKeys.length; i++) {\r
- byte[] key = DerivePrivateKey.derivePrivateKey(privateKeys[i], 1, false, input.getControlProgramIndex());\r
+ System.out.println(input.isChange());\r
+ byte[] key = DerivePrivateKey.derivePrivateKey(privateKeys[i], 1, input.isChange(), input.getControlProgramIndex());\r
byte[] message = hashFn(Hex.decode(input.inputID), Hex.decode(transaction.txID));\r
byte[] expandedPrivateKey = ExpandedPrivateKey.ExpandedPrivateKey(key);\r
byte[] sig = Signer.Ed25519InnerSign(expandedPrivateKey, message);\r
input.witnessComponent.signatures[i] = Hex.toHexString(sig);\r
- byte[] deriveXpub = DeriveXpub.deriveXpub(key);\r
+ byte[] deriveXpub = DeriveXpub.deriveXpub(expandedPrivateKey);\r
String publicKey = Hex.toHexString(deriveXpub).substring(0, 64);\r
- sb.append("20").append(publicKey);\r
+ sb.append(Integer.toString(Hex.decode(publicKey).length,16)).append(publicKey);\r
}\r
- //签名数跟公钥数相同\r
//TODO 签名数跟公钥数量不同\r
- sb.append("5").append(privateKeys.length).append("5").append(privateKeys.length).append("ad");\r
+ sb.append(Utils.pushDataInt(privateKeys.length)); //should be nrequired\r
+ sb.append(Utils.pushDataInt(privateKeys.length));\r
+ sb.append(OP_CHECKMULTISIG);\r
input.witnessComponent.signatures[privateKeys.length] = sb.toString();\r
\r
} catch (Exception e) {\r
\r
}\r
\r
- private byte[] hashFn(byte[] hashedInputHex, byte[] txID) {\r
+ public static byte[] hashFn(byte[] hashedInputHex, byte[] txID) {\r
\r
SHA3.Digest256 digest256 = new SHA3.Digest256();\r
// data = hashedInputHex + txID\r
} else {\r
privateChild = DerivePrivateKey.derivePrivateKey(rootPrivateKey, tx.inputs.get(i).getKeyIndex());\r
}\r
- buildWitness(tx, i, Hex.toHexString(privateChild));\r
+ buildWitness(tx, i, privateChild);\r
}\r
return serializeTransaction(tx);\r
}\r
import io.bytom.api.*;\r
import io.bytom.exception.BytomException;\r
import io.bytom.http.Client;\r
+import org.bouncycastle.util.encoders.Hex;\r
import org.junit.Test;\r
\r
import java.security.InvalidKeyException;\r
// .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
// setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0))\r
.addInput(input.setType(1))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(170000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(49100000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
.addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(10000000).setControlProgram("0020fa56ca7d47f8528e68e120d0e052885faeb9d090d238fa4266bdde21b137513c"))\r
.build(200000);\r
io.bytom.api.Transaction transaction = MapTransaction.mapTx(Transaction);\r
String issueAssetId = "a680606d49daae62ef9cb03263ca82a0b1e3184bb6311ea52a5189207f718789";\r
String program = "ae204cae24c2cec15491e70fc554026469496e373df9b9970b23acac8b782da0822d5151ad";\r
String assetDefine = "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d";\r
+ Transaction.AnnotatedInput input = btmUtxoToInput();\r
Transaction Transaction = new Transaction.Builder()\r
.addInput(new Transaction.AnnotatedInput().setType(0).setAssetId(issueAssetId).setControlProgram(program).setAmount(100000000).setAssetDefinition(assetDefine).setChange(false).setKeyIndex(13))\r
- .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
- setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0))\r
+// .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
+// setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0))\r
+ .addInput(input.setType(1))\r
.addOutput(new Transaction.AnnotatedOutput().setAssetId(issueAssetId).setAmount(100000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(870000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
+// .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(870000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
.build(2000000);\r
MapTransaction.mapTx(Transaction);\r
SignTransaction sign = new SignTransaction();\r
//retire asset\r
@Test\r
public void testRetire() throws NoSuchAlgorithmException, SignatureException, InvalidKeyException {\r
- String assetId1 = "8e962912423d8aea3409d1754782e7910da81b66c640aece14a6dac238f38e9b";\r
+ String arbitrary = "77656c636f6d65efbc8ce6aca2e8bf8ee69da5e588b0e58e9fe5ad90e4b896e7958c";\r
+ String retireControlProgram = "6a"+Integer.toString(Hex.decode(arbitrary).length,16)+arbitrary;\r
+ String assetId1 = "207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf";\r
Transaction transaction = new Transaction.Builder()\r
- .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(890000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
- setChange(false).setControlProgramIndex(2).setSourceId("6026b1acb11f3cbfb5280865ea857117a76d41ba7d60509dd358648424d8496a").setSourcePosition(0))\r
- .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(assetId1).setAmount(100000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
- setChange(false).setControlProgramIndex(2).setSourceId("d53e7ccfa06d3b27933a44e5d6e3e288edfc7e38f5396b8552ef44cf58a20347").setSourcePosition(0))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
- //arbitrary 加在retire control program 后面\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(assetId1).setAmount(100000000).setControlProgram("6a"))\r
+ .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(289100000).setControlProgram("0014f1dc52048f439ac7fd74f8106a21da78f00de48f").\r
+ setChange(true).setControlProgramIndex(41).setSourceId("0b2cff11d1d056d95237a5f2d06059e5395e86f60e69c1e8201ea624911c0c65").setSourcePosition(0))\r
+ .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(assetId1).setAmount(70000000000l).setControlProgram("0014bb8a039726df1b649738e9973db14a4b4fd4becf").\r
+ setChange(true).setControlProgramIndex(26).setSourceId("be0ac837e832c34a02968e54dab4f95cbeceb9fb01cd378310f6ea32219ee29b").setSourcePosition(1))\r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(279100000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(assetId1).setAmount(10000000000l).setControlProgram(retireControlProgram))\r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(assetId1).setAmount(60000000000l).setControlProgram("0014bb8a039726df1b649738e9973db14a4b4fd4becf"))\r
.build(2000000);\r
MapTransaction.mapTx(transaction);\r
SignTransaction sign = new SignTransaction();\r
\r
//utxo\r
private Transaction.AnnotatedInput btmUtxoToInput() {\r
- String utxoJson = "{\n" +\r
- " \"id\": \"cf2f5c7340490d33d535a680dc8d95bb66fcccbf1045706484621cc067b982ae\",\n" +\r
- " \"amount\": 70000000,\n" +\r
- " \"address\": \"tm1qf4g97wae3fsz973huwrjqnd68v530nmd7n2pc43zfpw9tvd30qfsd7jl8p\",\n" +\r
- " \"program\": \"00204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813\",\n" +\r
+ String utxoJson = "\n" +\r
+ "{\n" +\r
+ " \"id\": \"687e3c3ca1ee8139e57f43697db6aaeac95b10c75b828ef2fad30abe7d047e6a\",\n" +\r
+ " \"amount\": 10000000,\n" +\r
+ " \"address\": \"tm1qznfky62w4napzrwzphk804ss6g35p72mcw53q7\",\n" +\r
+ " \"program\": \"001414d362694eacfa110dc20dec77d610d22340f95b\",\n" +\r
" \"change\": false,\n" +\r
- " \"highest\": 140925,\n" +\r
- " \"account_alias\": \"mutiaccout\",\n" +\r
+ " \"highest\": 141905,\n" +\r
+ " \"account_alias\": \"wyjbtm\",\n" +\r
" \"asset_id\": \"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n" +\r
" \"asset_alias\": \"BTM\",\n" +\r
- " \"account_id\": \"0PCB0S1GG0A02\",\n" +\r
+ " \"account_id\": \"0NNSS39M00A02\",\n" +\r
" \"control_program_index\": 2,\n" +\r
- " \"source_id\": \"9b29c72a653f986d5c5a7bf16c0fe63a9f639a0d15f3faeabeb4c14df70bbd91\",\n" +\r
- " \"source_pos\": 0,\n" +\r
+ " \"source_id\": \"535b88d3f6b449fdba678b00b84d4b516df1da73104d689d41f964389f5a9217\",\n" +\r
+ " \"source_pos\": 1,\n" +\r
" \"valid_height\": 0,\n" +\r
" \"derive_rule\": 0\n" +\r
"}";\r
@Test\r
public void SubmitTransaction() throws BytomException {\r
Client client = TestUtil.generateClient();\r
- String raw = "0701c09a0c01016b01699b29c72a653f986d5c5a7bf16c0fe63a9f639a0d15f3faeabeb4c14df70bbd91ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80bbb02100012200204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813ac020440290bc8593d429d5c7d02f96232cf8035d3776eebf2a7e855c906cdbcf35281f98575624e326fbf1f9e8de70a7047b5af2f43c1d102fcf632d1544cff46aa970540ff237b6d2c5760bf633b640e120600d06e57ab3119d192b33894967a74293531507df473235233033f12c493bc005c8d1e2f858524a431edc7d522891dfada04406ebebe5d380e129fb212a777aca0f971cfe38a2e54cd9b822459609664303aa2e10caa10f5cb8eae4a53688f895a9cbe13e5be085dd289251c63a7c86718730f67ae204e4fcad6d69dfbad1fa83c37e6fd2031476940b44a9165fa79084e5a4d9acaed20415a96ffead835222ee96eda7c16e99a4c87e8e5e43e54d2d493855f707baf78209613d3c8a4aa730bb24e0324a920b2e3c8db7260ded4527f6d6d7d14d86b64385353ad020148ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80e1eb17012200204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b1781300013cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ade2040116001414d362694eacfa110dc20dec77d610d22340f95b00";\r
+ String raw = "070180897a020160015e0b2cff11d1d056d95237a5f2d06059e5395e86f60e69c1e8201ea624911c0c65ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0a1ed89010001160014f1dc52048f439ac7fd74f8106a21da78f00de48f6302401660121218ab96d9f22cce712541ca34c53f4da40450669854341ca9624ad1cf10d1bfc96449fad5406224afd253ccfbdeab683f7ec7f9ee8f45e47a0c58500f2031ecc1bdd5fb9b40016358340b87646ea39faf55c0c105205cfdfdc6184725f40161015fbe0ac837e832c34a02968e54dab4f95cbeceb9fb01cd378310f6ea32219ee29b207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf80f8cce284020101160014bb8a039726df1b649738e9973db14a4b4fd4becf630240d7b7f1c2ca1048fd6798234f2a1e895762f83e802507a008eff52605611b67390a74eaf228b76f5589ff109b2c20eaa65fad6de2e5ab8a25b54267b607df970b20a71547e1064b5edaad92cdce6b0ace832836ba28fdeaf0b83010bed247fe927c03013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0f48a85010116001414d362694eacfa110dc20dec77d610d22340f95b00014b207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf80c8afa02501246a2277656c636f6d65efbc8ce6aca2e8bf8ee69da5e588b0e58e9fe5ad90e4b896e7958c00013e207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf80b09dc2df0101160014bb8a039726df1b649738e9973db14a4b4fd4becf00";\r
SubmitTransaction.SubmitResponse submitResponse = SubmitTransaction.submitRawTransaction(client, raw);\r
System.out.println(submitResponse.tx_id);\r
}\r
// .addInput(new Transaction.AnnotatedInput().setType(1).setAssetId(btmAssetID).setAmount(880000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b").\r
// setChange(false).setControlProgramIndex(2).setSourceId("fc43933d1c601b2503b033e31d3bacfa5c40ccb2ff0be6e94d8332462e0928a3").setSourcePosition(0))\r
.addInput(input.setType(1))\r
- .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(50000000).setControlProgram("00204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813"))\r
+ .addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(80000000).setControlProgram("00204d505f3bb98a6022fa37e387204dba3b2917cf6df4d41c5622485c55b1b17813"))\r
.addOutput(new Transaction.AnnotatedOutput().setAssetId(btmAssetID).setAmount(10000000).setControlProgram("001414d362694eacfa110dc20dec77d610d22340f95b"))\r
.build(200000);\r
Transaction transaction = MapTransaction.mapTx(Transaction);\r