mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
fill in input panes with psbt information
This commit is contained in:
parent
5ad85eb154
commit
6f10f87c5b
18 changed files with 219 additions and 51 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
|||
Subproject commit 9d15c27bfd8bd6c51f03fe081d6e70718ecf2eb0
|
||||
Subproject commit c8226ea947d910186d3a2e37ba9c5e85c2ec09ef
|
|
@ -108,6 +108,9 @@ public class AppController implements Initializable {
|
|||
addTransactionTab("p2wsh", "0100000000010193a2db37b841b2a46f4e9bb63fe9c1012da3ab7fe30b9f9c974242778b5af8980000000000ffffffff01806fb307000000001976a914bbef244bcad13cffb68b5cef3017c7423675552288ac040047304402203cdcaf02a44e37e409646e8a506724e9e1394b890cb52429ea65bac4cc2403f1022024b934297bcd0c21f22cee0e48751c8b184cc3a0d704cae2684e14858550af7d01483045022100feb4e1530c13e72226dc912dcd257df90d81ae22dbddb5a3c2f6d86f81d47c8e022069889ddb76388fa7948aaa018b2480ac36132009bb9cfade82b651e88b4b137a01695221026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf32103befa190c0c22e2f53720b1be9476dcf11917da4665c44c9c71c3a2d28a933c352102be46dc245f58085743b1cc37c82f0d63a960efa43b5336534275fc469b49f4ac53ae00000000", null);
|
||||
addTransactionTab("test1", "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd0481500400002305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900", null);
|
||||
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) {
|
||||
|
@ -120,7 +123,7 @@ public class AppController implements Initializable {
|
|||
PSBT psbt = PSBT.fromString(psbtHex);
|
||||
addTransactionTab(name, null, psbt);
|
||||
} catch(Exception e) {
|
||||
//ignore
|
||||
System.out.println("Could not load PSBT: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
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.psbt.PSBTInput;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
|
@ -34,6 +37,15 @@ public class InputController extends TransactionFormController implements Initia
|
|||
@FXML
|
||||
private Button outpointSelect;
|
||||
|
||||
@FXML
|
||||
private TextField spends;
|
||||
|
||||
@FXML
|
||||
private Label from;
|
||||
|
||||
@FXML
|
||||
private TextField address;
|
||||
|
||||
@FXML
|
||||
private CodeArea scriptSigArea;
|
||||
|
||||
|
@ -103,22 +115,62 @@ public class InputController extends TransactionFormController implements Initia
|
|||
TransactionInput txInput = inputForm.getTransactionInput();
|
||||
PSBTInput psbtInput = inputForm.getPsbtInput();
|
||||
|
||||
inputFieldset.setText("Input #" + txInput.getIndex());
|
||||
outpoint.setText(txInput.getOutpoint().getHash().toString() + ":" + txInput.getOutpoint().getIndex());
|
||||
|
||||
//TODO: Enable select outpoint when wallet present
|
||||
outpointSelect.setDisable(true);
|
||||
initializeInputFields(txInput, psbtInput);
|
||||
initializeScriptFields(txInput, psbtInput);
|
||||
initializeStatusFields(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) {
|
||||
//TODO: Is this safe?
|
||||
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();
|
||||
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();
|
||||
if(redeemScript != null) {
|
||||
|
@ -129,18 +181,40 @@ public class InputController extends TransactionFormController implements Initia
|
|||
|
||||
witnessesArea.clear();
|
||||
witnessScriptArea.clear();
|
||||
Script witnesses = null;
|
||||
Script witnessScript = null;
|
||||
|
||||
if(txInput.hasWitness()) {
|
||||
List<ScriptChunk> witnessChunks = txInput.getWitness().asScriptChunks();
|
||||
if(witnessChunks.get(witnessChunks.size() - 1).isScript()) {
|
||||
Script witnessScript = new Script(witnessChunks.get(witnessChunks.size() - 1).getData());
|
||||
appendScript(witnessesArea, new Script(witnessChunks.subList(0, witnessChunks.size() - 1)), null, witnessScript);
|
||||
appendScript(witnessScriptArea, witnessScript);
|
||||
witnesses = new Script(witnessChunks.subList(0, witnessChunks.size() - 1));
|
||||
witnessScript = witnessChunks.get(witnessChunks.size() - 1).getScript();
|
||||
} else {
|
||||
appendScript(witnessesArea, new Script(witnessChunks));
|
||||
witnessScriptScroll.setDisable(true);
|
||||
witnesses = new Script(witnessChunks);
|
||||
}
|
||||
} 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 {
|
||||
witnessesScroll.setDisable(true);
|
||||
}
|
||||
|
||||
if(witnessScript != null) {
|
||||
appendScript(witnessScriptArea, witnessScript);
|
||||
} else {
|
||||
witnessScriptScroll.setDisable(true);
|
||||
}
|
||||
}
|
||||
|
@ -152,13 +226,23 @@ public class InputController extends TransactionFormController implements Initia
|
|||
if(inputForm.getPsbtInput() != null) {
|
||||
PSBTInput psbtInput = inputForm.getPsbtInput();
|
||||
|
||||
try {
|
||||
int reqSigs = psbtInput.getSigningScript().getNumRequiredSignatures();
|
||||
int foundSigs = psbtInput.getPartialSignatures().size();
|
||||
signatures.setText(foundSigs + "/" + reqSigs);
|
||||
} catch (NonStandardScriptException e) {
|
||||
//TODO: Handle unusual transaction sig
|
||||
int reqSigs = -1;
|
||||
if((psbtInput.getNonWitnessUtxo() != null || psbtInput.getWitnessUtxo() != null) && psbtInput.getSigningScript() != null) {
|
||||
try {
|
||||
reqSigs = psbtInput.getSigningScript().getNumRequiredSignatures();
|
||||
} catch (NonStandardScriptException e) {
|
||||
//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());
|
||||
|
@ -280,4 +364,28 @@ public class InputController extends TransactionFormController implements Initia
|
|||
this.inputForm = form;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class InputsController extends TransactionFormController implements Initi
|
|||
if(inputsForm.getPsbt() != null) {
|
||||
int reqSigs = 0;
|
||||
int foundSigs = 0;
|
||||
boolean showDenominator = true;
|
||||
|
||||
List<TransactionOutput> outputs = new ArrayList<>();
|
||||
for(int i = 0; i < tx.getInputs().size(); i++) {
|
||||
|
@ -59,11 +60,23 @@ public class InputsController extends TransactionFormController implements Initi
|
|||
outputs.add(psbtInput.getWitnessUtxo());
|
||||
}
|
||||
|
||||
try {
|
||||
reqSigs += psbtInput.getSigningScript().getNumRequiredSignatures();
|
||||
if((psbtInput.getNonWitnessUtxo() != null || psbtInput.getWitnessUtxo() != null) && psbtInput.getSigningScript() != null) {
|
||||
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();
|
||||
} catch (NonStandardScriptException e) {
|
||||
//TODO: Handle unusual transaction sig
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +85,12 @@ public class InputsController extends TransactionFormController implements Initi
|
|||
totalAmt += output.getValue();
|
||||
}
|
||||
total.setText(totalAmt + " sats");
|
||||
signatures.setText(foundSigs + "/" + reqSigs);
|
||||
if(showDenominator) {
|
||||
signatures.setText(foundSigs + "/" + reqSigs);
|
||||
} else {
|
||||
signatures.setText(foundSigs + "/?");
|
||||
}
|
||||
|
||||
addPieData(inputsPie, outputs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.address.Address;
|
||||
import com.sparrowwallet.drongo.protocol.NonStandardScriptException;
|
||||
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
import tornadofx.control.Fieldset;
|
||||
|
@ -19,6 +22,12 @@ public class OutputController extends TransactionFormController implements Initi
|
|||
@FXML
|
||||
private TextField value;
|
||||
|
||||
@FXML
|
||||
private Label to;
|
||||
|
||||
@FXML
|
||||
private TextField address;
|
||||
|
||||
@FXML
|
||||
private CodeArea scriptPubKeyArea;
|
||||
|
||||
|
@ -31,8 +40,21 @@ public class OutputController extends TransactionFormController implements Initi
|
|||
TransactionOutput txOutput = outputForm.getTransactionOutput();
|
||||
|
||||
outputFieldset.setText("Output #" + txOutput.getIndex());
|
||||
|
||||
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();
|
||||
appendScript(scriptPubKeyArea, txOutput.getScript(), null, null);
|
||||
}
|
||||
|
|
|
@ -182,13 +182,15 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
if(transaction.hasWitnesses()) {
|
||||
for (int i = 0; i < transaction.getInputs().size(); i++) {
|
||||
TransactionInput input = transaction.getInputs().get(i);
|
||||
TransactionWitness witness = input.getWitness();
|
||||
VarInt witnessCount = new VarInt(witness.getPushCount());
|
||||
cursor = addText(hex, cursor, witnessCount.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "count"));
|
||||
for(byte[] push : witness.getPushes()) {
|
||||
VarInt witnessLen = new VarInt(push.length);
|
||||
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"));
|
||||
if(input.hasWitness()) {
|
||||
TransactionWitness witness = input.getWitness();
|
||||
VarInt witnessCount = new VarInt(witness.getPushCount());
|
||||
cursor = addText(hex, cursor, witnessCount.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "count"));
|
||||
for(byte[] push : witness.getPushes()) {
|
||||
VarInt witnessLen = new VarInt(push.length);
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public abstract class TransactionFormController {
|
|||
} else if(chunk.isSignature()) {
|
||||
codeArea.append("<signature" + signatureCount++ + ">", "script-signature");
|
||||
} else if(chunk.isScript()) {
|
||||
Script nestedScript = new Script(chunk.getData());
|
||||
Script nestedScript = chunk.getScript();
|
||||
if (nestedScript.equals(redeemScript)) {
|
||||
codeArea.append("<RedeemScript>", "script-redeem");
|
||||
} else if (nestedScript.equals(witnessScript)) {
|
||||
|
@ -132,7 +132,7 @@ public abstract class TransactionFormController {
|
|||
ScriptChunk hoverChunk = script.getChunks().get(position.getMajor()/2);
|
||||
if(!hoverChunk.isOpCode()) {
|
||||
Point2D pos = e.getScreenPosition();
|
||||
popupMsg.setText(hoverChunk.toString());
|
||||
popupMsg.setText(describeScriptChunk(hoverChunk));
|
||||
popup.show(area, pos.getX(), pos.getY() + 10);
|
||||
}
|
||||
}
|
||||
|
@ -141,4 +141,8 @@ public abstract class TransactionFormController {
|
|||
popup.hide();
|
||||
});
|
||||
}
|
||||
|
||||
protected String describeScriptChunk(ScriptChunk chunk) {
|
||||
return chunk.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<?import javafx.scene.control.*?>
|
||||
<?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>
|
||||
<MenuBar useSystemMenuBar="true">
|
||||
<menus>
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
-fx-pref-height: 25px;
|
||||
}
|
||||
|
||||
.form .input-container {
|
||||
-fx-spacing: 2;
|
||||
}
|
||||
|
||||
.form .field {
|
||||
-fx-padding: 5 5;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints minWidth="340" prefWidth="340"
|
||||
<ColumnConstraints minWidth="365" prefWidth="365"
|
||||
maxWidth="Infinity">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints minWidth="340" prefWidth="340"
|
||||
<ColumnConstraints minWidth="365" prefWidth="365"
|
||||
maxWidth="Infinity">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
|
@ -37,6 +37,11 @@
|
|||
</graphic>
|
||||
</Button>
|
||||
</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>
|
||||
</Form>
|
||||
|
||||
|
@ -48,7 +53,7 @@
|
|||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane>
|
||||
<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>
|
||||
</VirtualizedScrollPane>
|
||||
</HBox>
|
||||
|
@ -57,7 +62,7 @@
|
|||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane fx:id="redeemScriptScroll">
|
||||
<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>
|
||||
</VirtualizedScrollPane>
|
||||
</HBox>
|
||||
|
@ -66,7 +71,7 @@
|
|||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane fx:id="witnessesScroll">
|
||||
<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>
|
||||
</VirtualizedScrollPane>
|
||||
</HBox>
|
||||
|
@ -75,7 +80,7 @@
|
|||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane fx:id="witnessScriptScroll">
|
||||
<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>
|
||||
</VirtualizedScrollPane>
|
||||
</HBox>
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
|
@ -28,8 +28,10 @@
|
|||
</rowConstraints>
|
||||
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0">
|
||||
<Fieldset fx:id="outputFieldset" inputGrow="SOMETIMES" text="Output">
|
||||
<Field text="Value:">
|
||||
<TextField fx:id="value" editable="false" styleClass="copyable-label" />
|
||||
<Field text="Sends:">
|
||||
<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>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
@ -42,7 +44,7 @@
|
|||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane>
|
||||
<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>
|
||||
</VirtualizedScrollPane>
|
||||
</HBox>
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="340" prefWidth="340">
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="365" prefWidth="365">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
|
|
BIN
src/main/resources/sparrow-nodrop.png
Normal file
BIN
src/main/resources/sparrow-nodrop.png
Normal file
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 |
Loading…
Reference in a new issue