fill in input panes with psbt information

This commit is contained in:
Craig Raw 2020-04-09 14:36:37 +02:00
parent 5ad85eb154
commit 6f10f87c5b
18 changed files with 219 additions and 51 deletions

2
drongo

@ -1 +1 @@
Subproject commit 9d15c27bfd8bd6c51f03fe081d6e70718ecf2eb0 Subproject commit c8226ea947d910186d3a2e37ba9c5e85c2ec09ef

View file

@ -108,6 +108,9 @@ public class AppController implements Initializable {
addTransactionTab("p2wsh", "0100000000010193a2db37b841b2a46f4e9bb63fe9c1012da3ab7fe30b9f9c974242778b5af8980000000000ffffffff01806fb307000000001976a914bbef244bcad13cffb68b5cef3017c7423675552288ac040047304402203cdcaf02a44e37e409646e8a506724e9e1394b890cb52429ea65bac4cc2403f1022024b934297bcd0c21f22cee0e48751c8b184cc3a0d704cae2684e14858550af7d01483045022100feb4e1530c13e72226dc912dcd257df90d81ae22dbddb5a3c2f6d86f81d47c8e022069889ddb76388fa7948aaa018b2480ac36132009bb9cfade82b651e88b4b137a01695221026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf32103befa190c0c22e2f53720b1be9476dcf11917da4665c44c9c71c3a2d28a933c352102be46dc245f58085743b1cc37c82f0d63a960efa43b5336534275fc469b49f4ac53ae00000000", null); addTransactionTab("p2wsh", "0100000000010193a2db37b841b2a46f4e9bb63fe9c1012da3ab7fe30b9f9c974242778b5af8980000000000ffffffff01806fb307000000001976a914bbef244bcad13cffb68b5cef3017c7423675552288ac040047304402203cdcaf02a44e37e409646e8a506724e9e1394b890cb52429ea65bac4cc2403f1022024b934297bcd0c21f22cee0e48751c8b184cc3a0d704cae2684e14858550af7d01483045022100feb4e1530c13e72226dc912dcd257df90d81ae22dbddb5a3c2f6d86f81d47c8e022069889ddb76388fa7948aaa018b2480ac36132009bb9cfade82b651e88b4b137a01695221026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf32103befa190c0c22e2f53720b1be9476dcf11917da4665c44c9c71c3a2d28a933c352102be46dc245f58085743b1cc37c82f0d63a960efa43b5336534275fc469b49f4ac53ae00000000", null);
addTransactionTab("test1", "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd0481500400002305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900", null); addTransactionTab("test1", "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd0481500400002305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900", null);
addTransactionTab("3of3-1signed.psbt", null, "70736274ff0100550200000001294c4871c059bb76be81e94b78059ee2e0c9b1b47f38edb6b4e75916062394930000000000feffffff01f82a0000000000001976a914e65b294f890792f2c2725d488567018d660f0cf488ac701c09004f0102aa7ed3044b1635bb800000021bf4bfc48934b7966b39bdebb689525d9b8bfed5c8b16e8c58f9afe4641d6d5f03800b5dbec0355c9f0b5e8227bc903e9d0ff1fe6ced0dcfb6d416541c7412c4331406b57041300000800000008000000080020000804f0102aa7ed3042cd31dee80000002d544b2364010378f8c6cec85f6b7ed83a8203dcdbedb97e2625f431f897b837e0363428de8fcfbfe373c0d9e1e0cc8163d886764bafe71c5822eaa232981356589145f63394f300000800000008000000080020000804f0102aa7ed3049ec7d9f580000002793e04aff18b4e40ebc48bcdc6232c54c69cf7265a38fbd85b35705e34d2d42f03368e79aa2b2b7f736d156905a7a45891df07baa2d0b7f127a537908cb82deed514130a48af300000800000008000000080020000800001012b983a000000000000220020f64748dad1cbad107761aaed5c59f25aba006498d260b440e0a091691350c9aa010569532102f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3262103171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a221037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f753ae220602f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3261c130a48af300000800000008000000080020000800000000000000000220603171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a21c5f63394f300000800000008000000080020000800000000000000000220203171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a24830450221008d27cc4b03bc543726e73b69e7980e7364d6f33f979a5cd9b92fb3d050666bd002204fc81fc9c67baf7c3b77041ed316714a9c117a5bdbb020e8c771ea3bdc342434012206037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f71c06b570413000008000000080000000800200008000000000000000000000"); addTransactionTab("3of3-1signed.psbt", null, "70736274ff0100550200000001294c4871c059bb76be81e94b78059ee2e0c9b1b47f38edb6b4e75916062394930000000000feffffff01f82a0000000000001976a914e65b294f890792f2c2725d488567018d660f0cf488ac701c09004f0102aa7ed3044b1635bb800000021bf4bfc48934b7966b39bdebb689525d9b8bfed5c8b16e8c58f9afe4641d6d5f03800b5dbec0355c9f0b5e8227bc903e9d0ff1fe6ced0dcfb6d416541c7412c4331406b57041300000800000008000000080020000804f0102aa7ed3042cd31dee80000002d544b2364010378f8c6cec85f6b7ed83a8203dcdbedb97e2625f431f897b837e0363428de8fcfbfe373c0d9e1e0cc8163d886764bafe71c5822eaa232981356589145f63394f300000800000008000000080020000804f0102aa7ed3049ec7d9f580000002793e04aff18b4e40ebc48bcdc6232c54c69cf7265a38fbd85b35705e34d2d42f03368e79aa2b2b7f736d156905a7a45891df07baa2d0b7f127a537908cb82deed514130a48af300000800000008000000080020000800001012b983a000000000000220020f64748dad1cbad107761aaed5c59f25aba006498d260b440e0a091691350c9aa010569532102f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3262103171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a221037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f753ae220602f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3261c130a48af300000800000008000000080020000800000000000000000220603171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a21c5f63394f300000800000008000000080020000800000000000000000220203171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a24830450221008d27cc4b03bc543726e73b69e7980e7364d6f33f979a5cd9b92fb3d050666bd002204fc81fc9c67baf7c3b77041ed316714a9c117a5bdbb020e8c771ea3bdc342434012206037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f71c06b570413000008000000080000000800200008000000000000000000000");
addTransactionTab("bip174-signer.psbt", null, "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000");
addTransactionTab("bip174-combiner.psbt", null, "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000");
addTransactionTab("bip174-finalizer.psbt", null, "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000");
} }
private void addTransactionTab(String name, String transactionHex, String psbtHex) { private void addTransactionTab(String name, String transactionHex, String psbtHex) {
@ -120,7 +123,7 @@ public class AppController implements Initializable {
PSBT psbt = PSBT.fromString(psbtHex); PSBT psbt = PSBT.fromString(psbtHex);
addTransactionTab(name, null, psbt); addTransactionTab(name, null, psbt);
} catch(Exception e) { } catch(Exception e) {
//ignore System.out.println("Could not load PSBT: " + e.getMessage());
} }
} }
} }

View file

@ -1,5 +1,8 @@
package com.sparrowwallet.sparrow.transaction; package com.sparrowwallet.sparrow.transaction;
import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.address.Address;
import com.sparrowwallet.drongo.crypto.ECKey;
import com.sparrowwallet.drongo.protocol.*; import com.sparrowwallet.drongo.protocol.*;
import com.sparrowwallet.drongo.psbt.PSBTInput; import com.sparrowwallet.drongo.psbt.PSBTInput;
import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.EventManager;
@ -34,6 +37,15 @@ public class InputController extends TransactionFormController implements Initia
@FXML @FXML
private Button outpointSelect; private Button outpointSelect;
@FXML
private TextField spends;
@FXML
private Label from;
@FXML
private TextField address;
@FXML @FXML
private CodeArea scriptSigArea; private CodeArea scriptSigArea;
@ -103,22 +115,62 @@ public class InputController extends TransactionFormController implements Initia
TransactionInput txInput = inputForm.getTransactionInput(); TransactionInput txInput = inputForm.getTransactionInput();
PSBTInput psbtInput = inputForm.getPsbtInput(); PSBTInput psbtInput = inputForm.getPsbtInput();
inputFieldset.setText("Input #" + txInput.getIndex()); initializeInputFields(txInput, psbtInput);
outpoint.setText(txInput.getOutpoint().getHash().toString() + ":" + txInput.getOutpoint().getIndex());
//TODO: Enable select outpoint when wallet present
outpointSelect.setDisable(true);
initializeScriptFields(txInput, psbtInput); initializeScriptFields(txInput, psbtInput);
initializeStatusFields(txInput); initializeStatusFields(txInput);
initializeLocktimeFields(txInput); initializeLocktimeFields(txInput);
} }
private void initializeInputFields(TransactionInput txInput, PSBTInput psbtInput) {
inputFieldset.setText("Input #" + txInput.getIndex());
outpoint.setText(txInput.getOutpoint().getHash().toString() + ":" + txInput.getOutpoint().getIndex());
spends.setText("Unknown");
from.setVisible(false);
if(psbtInput != null) {
TransactionOutput output = null;
if(psbtInput.getNonWitnessUtxo() != null) {
output = psbtInput.getNonWitnessUtxo().getOutputs().get(txInput.getIndex());
} else if(psbtInput.getWitnessUtxo() != null) {
output = psbtInput.getWitnessUtxo();
}
if(output != null) {
spends.setText(output.getValue() + " sats");
try {
Address[] addresses = output.getScript().getToAddresses();
from.setVisible(true);
if(addresses.length == 1) {
address.setText(addresses[0].getAddress());
} else {
address.setText("multiple addresses");
}
} catch(NonStandardScriptException e) {
//ignore
}
}
}
//TODO: Enable select outpoint when wallet present
outpointSelect.setDisable(true);
}
private void initializeScriptFields(TransactionInput txInput, PSBTInput psbtInput) { private void initializeScriptFields(TransactionInput txInput, PSBTInput psbtInput) {
//TODO: Is this safe? //TODO: Is this safe?
Script redeemScript = txInput.getScriptSig().getFirstNestedScript(); Script redeemScript = txInput.getScriptSig().getFirstNestedScript();
if(redeemScript == null && psbtInput != null && psbtInput.getRedeemScript() != null) {
redeemScript = psbtInput.getRedeemScript();
}
if(redeemScript == null && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
redeemScript = psbtInput.getFinalScriptSig().getFirstNestedScript();
}
scriptSigArea.clear(); scriptSigArea.clear();
appendScript(scriptSigArea, txInput.getScriptSig(), redeemScript, null); if(txInput.getScriptSig().isEmpty() && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
appendScript(scriptSigArea, psbtInput.getFinalScriptSig(), redeemScript, null);
} else {
appendScript(scriptSigArea, txInput.getScriptSig(), redeemScript, null);
}
redeemScriptArea.clear(); redeemScriptArea.clear();
if(redeemScript != null) { if(redeemScript != null) {
@ -129,18 +181,40 @@ public class InputController extends TransactionFormController implements Initia
witnessesArea.clear(); witnessesArea.clear();
witnessScriptArea.clear(); witnessScriptArea.clear();
Script witnesses = null;
Script witnessScript = null;
if(txInput.hasWitness()) { if(txInput.hasWitness()) {
List<ScriptChunk> witnessChunks = txInput.getWitness().asScriptChunks(); List<ScriptChunk> witnessChunks = txInput.getWitness().asScriptChunks();
if(witnessChunks.get(witnessChunks.size() - 1).isScript()) { if(witnessChunks.get(witnessChunks.size() - 1).isScript()) {
Script witnessScript = new Script(witnessChunks.get(witnessChunks.size() - 1).getData()); witnesses = new Script(witnessChunks.subList(0, witnessChunks.size() - 1));
appendScript(witnessesArea, new Script(witnessChunks.subList(0, witnessChunks.size() - 1)), null, witnessScript); witnessScript = witnessChunks.get(witnessChunks.size() - 1).getScript();
appendScript(witnessScriptArea, witnessScript);
} else { } else {
appendScript(witnessesArea, new Script(witnessChunks)); witnesses = new Script(witnessChunks);
witnessScriptScroll.setDisable(true);
} }
} else if(psbtInput != null) {
if(psbtInput.getFinalScriptWitness() != null) {
List<ScriptChunk> witnessChunks = psbtInput.getFinalScriptWitness().asScriptChunks();
if(witnessChunks.get(witnessChunks.size() - 1).isScript()) {
witnesses = new Script(witnessChunks.subList(0, witnessChunks.size() - 1));
witnessScript = witnessChunks.get(witnessChunks.size() - 1).getScript();
} else {
witnesses = new Script(witnessChunks);
}
} else if(psbtInput.getWitnessScript() != null) {
witnessScript = psbtInput.getWitnessScript();
}
}
if(witnesses != null) {
appendScript(witnessesArea, witnesses, null, witnessScript);
} else { } else {
witnessesScroll.setDisable(true); witnessesScroll.setDisable(true);
}
if(witnessScript != null) {
appendScript(witnessScriptArea, witnessScript);
} else {
witnessScriptScroll.setDisable(true); witnessScriptScroll.setDisable(true);
} }
} }
@ -152,13 +226,23 @@ public class InputController extends TransactionFormController implements Initia
if(inputForm.getPsbtInput() != null) { if(inputForm.getPsbtInput() != null) {
PSBTInput psbtInput = inputForm.getPsbtInput(); PSBTInput psbtInput = inputForm.getPsbtInput();
try { int reqSigs = -1;
int reqSigs = psbtInput.getSigningScript().getNumRequiredSignatures(); if((psbtInput.getNonWitnessUtxo() != null || psbtInput.getWitnessUtxo() != null) && psbtInput.getSigningScript() != null) {
int foundSigs = psbtInput.getPartialSignatures().size(); try {
signatures.setText(foundSigs + "/" + reqSigs); reqSigs = psbtInput.getSigningScript().getNumRequiredSignatures();
} catch (NonStandardScriptException e) { } catch (NonStandardScriptException e) {
//TODO: Handle unusual transaction sig //TODO: Handle unusual transaction sig
}
} }
int foundSigs = psbtInput.getPartialSignatures().size();
if(psbtInput.getFinalScriptWitness() != null) {
foundSigs = psbtInput.getFinalScriptWitness().getSignatures().size();
} else if(psbtInput.getFinalScriptSig() != null) {
foundSigs = psbtInput.getFinalScriptSig().getSignatures().size();
}
signatures.setText(foundSigs + "/" + (reqSigs < 0 ? "?" : reqSigs));
} }
rbf.setSelected(txInput.isReplaceByFeeEnabled()); rbf.setSelected(txInput.isReplaceByFeeEnabled());
@ -280,4 +364,28 @@ public class InputController extends TransactionFormController implements Initia
this.inputForm = form; this.inputForm = form;
initializeView(); initializeView();
} }
@Override
protected String describeScriptChunk(ScriptChunk chunk) {
String chunkString = super.describeScriptChunk(chunk);
ECKey pubKey = null;
if(chunk.isSignature()) {
if(inputForm.getPsbtInput() != null) {
TransactionSignature signature = chunk.getSignature();
pubKey = inputForm.getPsbtInput().getKeyForSignature(signature);
}
} else if(chunk.isPubKey()) {
pubKey = chunk.getPubKey();
}
if(inputForm.getPsbtInput() != null) {
KeyDerivation derivation = inputForm.getPsbtInput().getKeyDerivation(pubKey);
if(derivation != null) {
return "[" + derivation.toString() + "] " + chunkString;
}
}
return chunkString;
}
} }

View file

@ -47,6 +47,7 @@ public class InputsController extends TransactionFormController implements Initi
if(inputsForm.getPsbt() != null) { if(inputsForm.getPsbt() != null) {
int reqSigs = 0; int reqSigs = 0;
int foundSigs = 0; int foundSigs = 0;
boolean showDenominator = true;
List<TransactionOutput> outputs = new ArrayList<>(); List<TransactionOutput> outputs = new ArrayList<>();
for(int i = 0; i < tx.getInputs().size(); i++) { for(int i = 0; i < tx.getInputs().size(); i++) {
@ -59,11 +60,23 @@ public class InputsController extends TransactionFormController implements Initi
outputs.add(psbtInput.getWitnessUtxo()); outputs.add(psbtInput.getWitnessUtxo());
} }
try { if((psbtInput.getNonWitnessUtxo() != null || psbtInput.getWitnessUtxo() != null) && psbtInput.getSigningScript() != null) {
reqSigs += psbtInput.getSigningScript().getNumRequiredSignatures(); try {
reqSigs += psbtInput.getSigningScript().getNumRequiredSignatures();
} catch (NonStandardScriptException e) {
showDenominator = false;
//TODO: Handle unusual transaction sig
}
} else {
showDenominator = false;
}
if(psbtInput.getFinalScriptWitness() != null) {
foundSigs += psbtInput.getFinalScriptWitness().getSignatures().size();
} else if(psbtInput.getFinalScriptSig() != null) {
foundSigs += psbtInput.getFinalScriptSig().getSignatures().size();
} else {
foundSigs += psbtInput.getPartialSignatures().size(); foundSigs += psbtInput.getPartialSignatures().size();
} catch (NonStandardScriptException e) {
//TODO: Handle unusual transaction sig
} }
} }
@ -72,7 +85,12 @@ public class InputsController extends TransactionFormController implements Initi
totalAmt += output.getValue(); totalAmt += output.getValue();
} }
total.setText(totalAmt + " sats"); total.setText(totalAmt + " sats");
signatures.setText(foundSigs + "/" + reqSigs); if(showDenominator) {
signatures.setText(foundSigs + "/" + reqSigs);
} else {
signatures.setText(foundSigs + "/?");
}
addPieData(inputsPie, outputs); addPieData(inputsPie, outputs);
} }
} }

View file

@ -1,8 +1,11 @@
package com.sparrowwallet.sparrow.transaction; package com.sparrowwallet.sparrow.transaction;
import com.sparrowwallet.drongo.address.Address;
import com.sparrowwallet.drongo.protocol.NonStandardScriptException;
import com.sparrowwallet.drongo.protocol.TransactionOutput; import com.sparrowwallet.drongo.protocol.TransactionOutput;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import org.fxmisc.richtext.CodeArea; import org.fxmisc.richtext.CodeArea;
import tornadofx.control.Fieldset; import tornadofx.control.Fieldset;
@ -19,6 +22,12 @@ public class OutputController extends TransactionFormController implements Initi
@FXML @FXML
private TextField value; private TextField value;
@FXML
private Label to;
@FXML
private TextField address;
@FXML @FXML
private CodeArea scriptPubKeyArea; private CodeArea scriptPubKeyArea;
@ -31,8 +40,21 @@ public class OutputController extends TransactionFormController implements Initi
TransactionOutput txOutput = outputForm.getTransactionOutput(); TransactionOutput txOutput = outputForm.getTransactionOutput();
outputFieldset.setText("Output #" + txOutput.getIndex()); outputFieldset.setText("Output #" + txOutput.getIndex());
value.setText(txOutput.getValue() + " sats"); value.setText(txOutput.getValue() + " sats");
try {
Address[] addresses = txOutput.getScript().getToAddresses();
to.setVisible(true);
if(addresses.length == 1) {
address.setText(addresses[0].getAddress());
} else {
address.setText("multiple addresses");
}
} catch(NonStandardScriptException e) {
//ignore
}
scriptPubKeyArea.clear(); scriptPubKeyArea.clear();
appendScript(scriptPubKeyArea, txOutput.getScript(), null, null); appendScript(scriptPubKeyArea, txOutput.getScript(), null, null);
} }

View file

@ -182,13 +182,15 @@ public class TransactionController implements Initializable, TransactionListener
if(transaction.hasWitnesses()) { if(transaction.hasWitnesses()) {
for (int i = 0; i < transaction.getInputs().size(); i++) { for (int i = 0; i < transaction.getInputs().size(); i++) {
TransactionInput input = transaction.getInputs().get(i); TransactionInput input = transaction.getInputs().get(i);
TransactionWitness witness = input.getWitness(); if(input.hasWitness()) {
VarInt witnessCount = new VarInt(witness.getPushCount()); TransactionWitness witness = input.getWitness();
cursor = addText(hex, cursor, witnessCount.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "count")); VarInt witnessCount = new VarInt(witness.getPushCount());
for(byte[] push : witness.getPushes()) { cursor = addText(hex, cursor, witnessCount.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "count"));
VarInt witnessLen = new VarInt(push.length); for(byte[] push : witness.getPushes()) {
cursor = addText(hex, cursor, witnessLen.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "length")); VarInt witnessLen = new VarInt(push.length);
cursor = addText(hex, cursor, (int)witnessLen.value*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "data")); cursor = addText(hex, cursor, witnessLen.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "length"));
cursor = addText(hex, cursor, (int)witnessLen.value*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "data"));
}
} }
} }
} }

View file

@ -91,7 +91,7 @@ public abstract class TransactionFormController {
} else if(chunk.isSignature()) { } else if(chunk.isSignature()) {
codeArea.append("<signature" + signatureCount++ + ">", "script-signature"); codeArea.append("<signature" + signatureCount++ + ">", "script-signature");
} else if(chunk.isScript()) { } else if(chunk.isScript()) {
Script nestedScript = new Script(chunk.getData()); Script nestedScript = chunk.getScript();
if (nestedScript.equals(redeemScript)) { if (nestedScript.equals(redeemScript)) {
codeArea.append("<RedeemScript>", "script-redeem"); codeArea.append("<RedeemScript>", "script-redeem");
} else if (nestedScript.equals(witnessScript)) { } else if (nestedScript.equals(witnessScript)) {
@ -132,7 +132,7 @@ public abstract class TransactionFormController {
ScriptChunk hoverChunk = script.getChunks().get(position.getMajor()/2); ScriptChunk hoverChunk = script.getChunks().get(position.getMajor()/2);
if(!hoverChunk.isOpCode()) { if(!hoverChunk.isOpCode()) {
Point2D pos = e.getScreenPosition(); Point2D pos = e.getScreenPosition();
popupMsg.setText(hoverChunk.toString()); popupMsg.setText(describeScriptChunk(hoverChunk));
popup.show(area, pos.getX(), pos.getY() + 10); popup.show(area, pos.getX(), pos.getY() + 10);
} }
} }
@ -141,4 +141,8 @@ public abstract class TransactionFormController {
popup.hide(); popup.hide();
}); });
} }
protected String describeScriptChunk(ScriptChunk chunk) {
return chunk.toString();
}
} }

View file

@ -3,7 +3,7 @@
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="1000.0" fx:controller="com.sparrowwallet.sparrow.AppController" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"> <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="750.0" prefWidth="1100.0" fx:controller="com.sparrowwallet.sparrow.AppController" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
<children> <children>
<MenuBar useSystemMenuBar="true"> <MenuBar useSystemMenuBar="true">
<menus> <menus>

View file

@ -10,6 +10,10 @@
-fx-pref-height: 25px; -fx-pref-height: 25px;
} }
.form .input-container {
-fx-spacing: 2;
}
.form .field { .form .field {
-fx-padding: 5 5; -fx-padding: 5 5;
} }

View file

@ -18,10 +18,10 @@
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
</padding> </padding>
<columnConstraints> <columnConstraints>
<ColumnConstraints minWidth="340" prefWidth="340" <ColumnConstraints minWidth="365" prefWidth="365"
maxWidth="Infinity"> maxWidth="Infinity">
</ColumnConstraints> </ColumnConstraints>
<ColumnConstraints minWidth="340" prefWidth="340" <ColumnConstraints minWidth="365" prefWidth="365"
maxWidth="Infinity"> maxWidth="Infinity">
</ColumnConstraints> </ColumnConstraints>
</columnConstraints> </columnConstraints>

View file

@ -18,9 +18,9 @@
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
</padding> </padding>
<columnConstraints> <columnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
@ -37,6 +37,11 @@
</graphic> </graphic>
</Button> </Button>
</Field> </Field>
<Field text="Spends:">
<TextField fx:id="spends" editable="false" styleClass="copyable-label" maxWidth="80" />
<Label fx:id="from" text="from" maxWidth="30" style="-fx-padding: 0" />
<TextField fx:id="address" editable="false" styleClass="copyable-label, id" />
</Field>
</Fieldset> </Fieldset>
</Form> </Form>
@ -48,7 +53,7 @@
<HBox prefHeight="42"> <HBox prefHeight="42">
<VirtualizedScrollPane> <VirtualizedScrollPane>
<content> <content>
<CodeArea fx:id="scriptSigArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" /> <CodeArea fx:id="scriptSigArea" editable="false" minWidth="620" prefWidth="620" wrapText="true" styleClass="uneditable-codearea" />
</content> </content>
</VirtualizedScrollPane> </VirtualizedScrollPane>
</HBox> </HBox>
@ -57,7 +62,7 @@
<HBox prefHeight="42"> <HBox prefHeight="42">
<VirtualizedScrollPane fx:id="redeemScriptScroll"> <VirtualizedScrollPane fx:id="redeemScriptScroll">
<content> <content>
<CodeArea fx:id="redeemScriptArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" /> <CodeArea fx:id="redeemScriptArea" editable="false" minWidth="620" prefWidth="620" wrapText="true" styleClass="uneditable-codearea" />
</content> </content>
</VirtualizedScrollPane> </VirtualizedScrollPane>
</HBox> </HBox>
@ -66,7 +71,7 @@
<HBox prefHeight="42"> <HBox prefHeight="42">
<VirtualizedScrollPane fx:id="witnessesScroll"> <VirtualizedScrollPane fx:id="witnessesScroll">
<content> <content>
<CodeArea fx:id="witnessesArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" /> <CodeArea fx:id="witnessesArea" editable="false" minWidth="620" prefWidth="620" wrapText="true" styleClass="uneditable-codearea" />
</content> </content>
</VirtualizedScrollPane> </VirtualizedScrollPane>
</HBox> </HBox>
@ -75,7 +80,7 @@
<HBox prefHeight="42"> <HBox prefHeight="42">
<VirtualizedScrollPane fx:id="witnessScriptScroll"> <VirtualizedScrollPane fx:id="witnessScriptScroll">
<content> <content>
<CodeArea fx:id="witnessScriptArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" /> <CodeArea fx:id="witnessScriptArea" editable="false" minWidth="620" prefWidth="620" wrapText="true" styleClass="uneditable-codearea" />
</content> </content>
</VirtualizedScrollPane> </VirtualizedScrollPane>
</HBox> </HBox>

View file

@ -11,9 +11,9 @@
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
</padding> </padding>
<columnConstraints> <columnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>

View file

@ -17,9 +17,9 @@
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
</padding> </padding>
<columnConstraints> <columnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
@ -28,8 +28,10 @@
</rowConstraints> </rowConstraints>
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0"> <Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0">
<Fieldset fx:id="outputFieldset" inputGrow="SOMETIMES" text="Output"> <Fieldset fx:id="outputFieldset" inputGrow="SOMETIMES" text="Output">
<Field text="Value:"> <Field text="Sends:">
<TextField fx:id="value" editable="false" styleClass="copyable-label" /> <TextField fx:id="value" editable="false" styleClass="copyable-label" maxWidth="80"/>
<Label fx:id="to" text="to" />
<TextField fx:id="address" editable="false" styleClass="copyable-label, id" />
</Field> </Field>
</Fieldset> </Fieldset>
</Form> </Form>
@ -42,7 +44,7 @@
<HBox prefHeight="42"> <HBox prefHeight="42">
<VirtualizedScrollPane> <VirtualizedScrollPane>
<content> <content>
<CodeArea fx:id="scriptPubKeyArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" /> <CodeArea fx:id="scriptPubKeyArea" editable="false" minWidth="620" prefWidth="620" wrapText="true" styleClass="uneditable-codearea" />
</content> </content>
</VirtualizedScrollPane> </VirtualizedScrollPane>
</HBox> </HBox>

View file

@ -11,9 +11,9 @@
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
</padding> </padding>
<columnConstraints> <columnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340"> <ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
</ColumnConstraints> </ColumnConstraints>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB