\r
# tx_signer \r
\r
-Java implementation of signing transaction offline to bytomd and serializing transaction to submit. \r
+Java implementation of signing transaction offline.\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
+#### Add dependency to your project \r
\r
1. first get source code \r
\r
- ``` \r
+ ```\r
git clone https://github.com/Bytom/bytom-java-sdk.git \r
``` \r
\r
-2. get jar package \r
+2. install to maven repository\r
\r
``` \r
- $ mvn assembly:assembly -Dmaven.test.skip=true \r
+ $ mvn clean install -DskipTests \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
+3. add dependency\r
+ ```xml\r
+ <dependency>\r
+ <groupId>io.bytom</groupId>\r
+ <artifactId>tx-signer</artifactId>\r
+ <version>1.0.0</version>\r
+ </dependency>\r
+ ```\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
+## Example\r
\r
-```java\r
+#### build transaction with spend input\r
+```\r
+ String btmAssetID = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";\r
+ \r
+ // create spend input\r
+ SpendInput input = new SpendInput();\r
+ input.setAssetId(btmAssetID);\r
+ input.setAmount(9800000000L);\r
+ \r
+ // control program of spend utxo\r
+ input.setProgram("0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e");\r
+ \r
+ // source position of spend utxo\r
+ input.setSourcePosition(2);\r
+ \r
+ // source id of spend utxo\r
+ input.setSourceID("4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea");\r
+ \r
+ // is the spend utxo used for change\r
+ input.setChange(true);\r
+ \r
+ // BIP protocol for derived paths, default BIP44\r
+ input.setBipProtocol(BIPProtocol.BIP32);\r
+ \r
+ // contorl program index of spend utxo\r
+ input.setControlProgramIndex(457);\r
+ \r
+ // account index\r
+ input.setKeyIndex(1);\r
+ \r
+ // provide a root private key for signing\r
+ input.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257");\r
\r
-AnnotatedBaseInput\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
+ // build transaction with signature\r
+ Transaction tx = new Transaction.Builder()\r
+ .addInput(input)\r
+ .addOutput(new Output(btmAssetID, 8800000000L, "0014a82f02bc37bc5ed87d5f9fca02f8a6a7d89cdd5c"))\r
+ .addOutput(new Output(btmAssetID, 900000000L, "00200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66"))\r
+ .setTimeRange(0)\r
+ .build();\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 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
+ String rawTransaction = tx.rawTransaction();\r
+```\r
\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
- }\r
+#### build transaction with issuance input\r
```\r
+ IssuanceInput issuanceInput = new IssuanceInput();\r
+ issuanceInput.setAssetId("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14");\r
+ issuanceInput.setAmount(100000000000L);\r
+ \r
+ // issuance program\r
+ issuanceInput.setProgram("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad");\r
+ issuanceInput.setNonce("ac9d5a527f5ab00a");\r
+ \r
+ // asset index\r
+ issuanceInput.setKeyIndex(5);\r
+ \r
+ // raw asset definition\r
+ issuanceInput.setRawAssetDefinition("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d");\r
+ \r
+ // provide a root private key for signing\r
+ issuanceInput.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257");\r
+\r
+ SpendInput spendInput = new SpendInput();\r
+ spendInput.setAssetId(btmAssetID);\r
+ spendInput.setAmount(9800000000L);\r
+ spendInput.setProgram("0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e");\r
+ spendInput.setKeyIndex(1);\r
+ spendInput.setChange(true);\r
+ spendInput.setSourceID("4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea");\r
+ spendInput.setSourcePosition(2);\r
+ spendInput.setControlProgramIndex(457);\r
+ spendInput.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257");\r
+\r
+ Transaction tx = new Transaction.Builder()\r
+ .addInput(issuanceInput)\r
+ .addInput(spendInput)\r
+ .addOutput(new Output("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14", 100000000000L, "001437e1aec83a4e6587ca9609e4e5aa728db7007449"))\r
+ .addOutput(new Output(btmAssetID, 9700000000L, "00148be1104e04734e5edaba5eea2e85793896b77c56"))\r
+ .setTimeRange(0)\r
+ .build();\r
+\r
+ String rawTx = tx.rawTransaction();\r
\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
-}\r
+```
\ No newline at end of file