use of com.sparrowwallet.drongo.crypto.ChildNumber in project drongo by sparrowwallet.
the class OutputDescriptor method getChangeDerivation.
public List<ChildNumber> getChangeDerivation(int wildCardReplacement) {
if (isMultisig()) {
List<ChildNumber> path = new ArrayList<>();
path.add(new ChildNumber(1));
path.add(new ChildNumber(wildCardReplacement));
return path;
}
return getChangeDerivation(getSingletonExtendedPublicKey(), wildCardReplacement);
}
use of com.sparrowwallet.drongo.crypto.ChildNumber in project drongo by sparrowwallet.
the class PaymentCodeTest method testNotificationAddress.
@Test
public void testNotificationAddress() throws InvalidPaymentCodeException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, MnemonicException {
PaymentCode alicePaymentCode = new PaymentCode("PM8TJTLJbPRGxSbc8EJi42Wrr6QbNSaSSVJ5Y3E4pbCYiTHUskHg13935Ubb7q8tx9GVbh2UuRnBc3WSyJHhUrw8KhprKnn9eDznYGieTzFcwQRya4GA");
Address aliceNotificationAddress = alicePaymentCode.getNotificationAddress();
Assert.assertEquals("1JDdmqFLhpzcUwPeinhJbUPw4Co3aWLyzW", aliceNotificationAddress.toString());
ECKey alicePrivKey = DumpedPrivateKey.fromBase58("Kx983SRhAZpAhj7Aac1wUXMJ6XZeyJKqCxJJ49dxEbYCT4a1ozRD").getKey();
byte[] alicePayload = alicePaymentCode.getPayload();
Assert.assertEquals("010002b85034fb08a8bfefd22848238257b252721454bbbfba2c3667f168837ea2cdad671af9f65904632e2dcc0c6ad314e11d53fc82fa4c4ea27a4a14eccecc478fee00000000000000000000000000", Utils.bytesToHex(alicePayload));
PaymentCode paymentCodeBob = new PaymentCode("PM8TJS2JxQ5ztXUpBBRnpTbcUXbUHy2T1abfrb3KkAAtMEGNbey4oumH7Hc578WgQJhPjBxteQ5GHHToTYHE3A1w6p7tU6KSoFmWBVbFGjKPisZDbP97");
ECKey bobNotificationPubKey = paymentCodeBob.getNotificationKey();
Assert.assertEquals("024ce8e3b04ea205ff49f529950616c3db615b1e37753858cc60c1ce64d17e2ad8", Utils.bytesToHex(bobNotificationPubKey.getPubKey()));
TransactionOutPoint transactionOutPoint = new TransactionOutPoint(Sha256Hash.wrapReversed(Utils.hexToBytes("86f411ab1c8e70ae8a0795ab7a6757aea6e4d5ae1826fc7b8f00c597d500609c")), 1);
Assert.assertEquals("86f411ab1c8e70ae8a0795ab7a6757aea6e4d5ae1826fc7b8f00c597d500609c01000000", Utils.bytesToHex(transactionOutPoint.bitcoinSerialize()));
SecretPoint secretPoint = new SecretPoint(alicePrivKey.getPrivKeyBytes(), bobNotificationPubKey.getPubKey());
Assert.assertEquals("736a25d9250238ad64ed5da03450c6a3f4f8f4dcdf0b58d1ed69029d76ead48d", Utils.bytesToHex(secretPoint.ECDHSecretAsBytes()));
byte[] blindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), transactionOutPoint.bitcoinSerialize());
Assert.assertEquals("be6e7a4256cac6f4d4ed4639b8c39c4cb8bece40010908e70d17ea9d77b4dc57f1da36f2d6641ccb37cf2b9f3146686462e0fa3161ae74f88c0afd4e307adbd5", Utils.bytesToHex(blindingMask));
byte[] blindedPaymentCode = PaymentCode.blind(alicePayload, blindingMask);
Assert.assertEquals("010002063e4eb95e62791b06c50e1a3a942e1ecaaa9afbbeb324d16ae6821e091611fa96c0cf048f607fe51a0327f5e2528979311c78cb2de0d682c61e1180fc3d543b00000000000000000000000000", Utils.bytesToHex(blindedPaymentCode));
Transaction transaction = new Transaction();
List<ScriptChunk> inputChunks = List.of(ScriptChunk.fromData(Utils.hexToBytes("3045022100ac8c6dbc482c79e86c18928a8b364923c774bfdbd852059f6b3778f2319b59a7022029d7cc5724e2f41ab1fcfc0ba5a0d4f57ca76f72f19530ba97c860c70a6bf0a801")), ScriptChunk.fromData(alicePrivKey.getPubKey()));
transaction.addInput(transactionOutPoint.getHash(), transactionOutPoint.getIndex(), new Script(inputChunks));
transaction.addOutput(10000, paymentCodeBob.getNotificationAddress());
List<ScriptChunk> opReturnChunks = List.of(ScriptChunk.fromOpcode(ScriptOpCodes.OP_RETURN), ScriptChunk.fromData(blindedPaymentCode));
transaction.addOutput(10000, new Script(opReturnChunks));
Assert.assertEquals("010000000186f411ab1c8e70ae8a0795ab7a6757aea6e4d5ae1826fc7b8f00c597d500609c010000006b483045022100ac8c6dbc482c79e86c18928a8b364923c774bfdb" + "d852059f6b3778f2319b59a7022029d7cc5724e2f41ab1fcfc0ba5a0d4f57ca76f72f19530ba97c860c70a6bf0a801210272d83d8a1fa323feab1c085157a0791b46eba34afb8bfbfaeb3a3fcc3f2" + "c9ad8ffffffff0210270000000000001976a9148066a8e7ee82e5c5b9b7dc1765038340dc5420a988ac1027000000000000536a4c50010002063e4eb95e62791b06c50e1a3a942e1ecaaa9afbbeb3" + "24d16ae6821e091611fa96c0cf048f607fe51a0327f5e2528979311c78cb2de0d682c61e1180fc3d543b0000000000000000000000000000000000", Utils.bytesToHex(transaction.bitcoinSerialize()));
Assert.assertEquals("9414f1681fb1255bd168a806254321a837008dd4480c02226063183deb100204", transaction.getTxId().toString());
ECKey alicePubKey = ECKey.fromPublicOnly(transaction.getInputs().get(0).getScriptSig().getChunks().get(1).data);
Assert.assertArrayEquals(alicePubKey.getPubKey(), alicePrivKey.getPubKey());
DeterministicSeed bobSeed = new DeterministicSeed("reward upper indicate eight swift arch injury crystal super wrestle already dentist", "", 0, DeterministicSeed.Type.BIP39);
Keystore bobKeystore = Keystore.fromSeed(bobSeed, List.of(new ChildNumber(47, true), ChildNumber.ZERO_HARDENED, ChildNumber.ZERO_HARDENED));
ECKey bobNotificationPrivKey = bobKeystore.getBip47ExtendedPrivateKey().getKey(List.of(ChildNumber.ZERO_HARDENED, new ChildNumber(0)));
SecretPoint bobSecretPoint = new SecretPoint(bobNotificationPrivKey.getPrivKeyBytes(), alicePubKey.getPubKey());
Assert.assertEquals("736a25d9250238ad64ed5da03450c6a3f4f8f4dcdf0b58d1ed69029d76ead48d", Utils.bytesToHex(bobSecretPoint.ECDHSecretAsBytes()));
byte[] bobBlindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), transaction.getInputs().get(0).getOutpoint().bitcoinSerialize());
Assert.assertEquals("be6e7a4256cac6f4d4ed4639b8c39c4cb8bece40010908e70d17ea9d77b4dc57f1da36f2d6641ccb37cf2b9f3146686462e0fa3161ae74f88c0afd4e307adbd5", Utils.bytesToHex(bobBlindingMask));
PaymentCode unblindedPaymentCode = new PaymentCode(PaymentCode.blind(transaction.getOutputs().get(1).getScript().getChunks().get(1).data, blindingMask));
Assert.assertEquals(alicePaymentCode, unblindedPaymentCode);
PaymentCode unblindedPaymentCode2 = PaymentCode.getPaymentCode(transaction, bobKeystore);
Assert.assertEquals(alicePaymentCode, unblindedPaymentCode2);
}
use of com.sparrowwallet.drongo.crypto.ChildNumber in project drongo by sparrowwallet.
the class WalletNode method compareTo.
@Override
public int compareTo(WalletNode node) {
if (getDerivation().size() != node.getDerivation().size()) {
return getDerivation().size() - node.getDerivation().size();
}
for (int i = 0; i < getDerivation().size(); i++) {
ChildNumber thisChild = getDerivation().get(i);
ChildNumber nodeChild = node.getDerivation().get(i);
if (thisChild.num() != nodeChild.num()) {
return thisChild.num() - nodeChild.num();
}
}
return 0;
}
use of com.sparrowwallet.drongo.crypto.ChildNumber in project drongo by sparrowwallet.
the class PSBTEntry method readBIP32Derivation.
public static List<ChildNumber> readBIP32Derivation(byte[] data) {
List<ChildNumber> path = new ArrayList<>();
ByteBuffer bb = ByteBuffer.wrap(data);
byte[] buf = new byte[4];
do {
bb.get(buf);
Utils.reverse(buf);
ByteBuffer pbuf = ByteBuffer.wrap(buf);
path.add(new ChildNumber(pbuf.getInt()));
} while (bb.hasRemaining());
return path;
}
use of com.sparrowwallet.drongo.crypto.ChildNumber in project drongo by sparrowwallet.
the class PSBTEntry method serializeKeyDerivation.
public static byte[] serializeKeyDerivation(KeyDerivation keyDerivation) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] fingerprintBytes = Utils.hexToBytes(keyDerivation.getMasterFingerprint());
if (fingerprintBytes.length != 4) {
throw new IllegalArgumentException("Invalid number of fingerprint bytes: " + fingerprintBytes.length);
}
baos.writeBytes(fingerprintBytes);
for (ChildNumber childNumber : keyDerivation.getDerivation()) {
byte[] indexBytes = new byte[4];
Utils.uint32ToByteArrayLE(childNumber.i(), indexBytes, 0);
baos.writeBytes(indexBytes);
}
return baos.toByteArray();
}
Aggregations