private void AddInputs(Transaction transaction, ExtPubKey pubKey, List <Coin> coins, int addressNumber, ref int index, Money money) { Base58CheckEncoder base58CheckEncoder = new Base58CheckEncoder(); var bytes = base58CheckEncoder.DecodeData(pubKey.GetWif(Network.Main).ToString()); string hex = BitConverter.ToString(bytes).Replace("-", "").ToLower(); Money spentMoney = Money.Zero; for (int i = 0; i < coins.Count; i++) { transaction.AddInput(new TxIn(coins[i].Outpoint)); var s = "01ff4c53ff" + hex + "0000" + (addressNumber > 9 ? addressNumber.ToString() : "0" + addressNumber) + "00"; transaction.Inputs[i + index].ScriptSig = new Script(s); spentMoney += coins[i].Amount; if (spentMoney >= money) { if (spentMoney - money > 0) { transaction.AddOutput(spentMoney - money, pubKey.Derive(0).Derive((uint)addressNumber).PubKey.Hash); } index = i + 1; return; } } index = coins.Count; }
public void ShouldFindUnsedKeyFarFarAway() { var filters = Enumerable.Range(0, 100).Select(x => CreateFiltersWith(GetScripts(true, x * 250, 250))).ToArray(); var unusedKeyIndex = ExtPubKeyExplorer.GetUnusedBech32Keys(1, true, ExtPubKey.GetWif(Network.Main), filters).First().ScriptPubKey.ToCompressedBytes(); Assert.Equal(DerivateScript(true, 25_000), unusedKeyIndex); }
public void ShouldFindNeverUsedKey() { var filters = new[] { FilterModel.FromHeightlessLine("000000000000de90e633e1b1330859842795d39018d033044e8b003e8cbf58e4:050a2f58828c9820642769ae320a40", 0) }; var unusedKeyIndex = ExtPubKeyExplorer.GetUnusedBech32Keys(1, true, ExtPubKey.GetWif(Network.Main), filters).First().ScriptPubKey.ToCompressedBytes(); Assert.Equal(DerivateScript(true, 0), unusedKeyIndex); }
public void ShouldProduceCorrectExtPubKey() { // This test is a replicate of 'should produce correct extpubkey' test in Angular (City Hub). var passphrase = ""; var recoveryPhrase = "mystery problem faith negative member bottom concert bundle asthma female process twelve"; var walletPassword = "******"; var network = new CityMain(); var chainCode = new byte[] { 166, 209, 155, 88, 182, 124, 193, 127, 139, 220, 152, 1, 213, 145, 245, 80, 118, 188, 53, 211, 33, 37, 158, 40, 118, 207, 42, 83, 219, 233, 188, 161 }; // Intentionally blank lines to be // line-compatible with JavaScript unit test. // The master node is made without network information, always same no matter network. ExtKey masterNode = HdOperations.GetExtendedKey(recoveryPhrase, passphrase); ExtPubKey extPubKey = masterNode.Neuter(); // masterNode in C# and JavaScript should both have the same chaincode at this step, verify: Assert.Equal(chainCode, masterNode.ChainCode); Assert.Equal(chainCode, extPubKey.ChainCode); // Get the private key in WIF format and verify. var xprv = masterNode.GetWif(network).ToWif(); Assert.Equal("xprv9s21ZrQH143K3ignAgXxaBbyVbrCTuUJSHNrMwdTa7n4i1zpFsiWdRCerTWrKaZXVehZFbXcFtwnmndrzC1AVs1BueiycVSxXjMyhXHpBqx", xprv); // Get the public key in WIF format and verify. var xpub = extPubKey.GetWif(network).ToWif(); Assert.Equal("xpub661MyMwAqRbcGCmFGi4xwKYi3dggsNC9oWJTAL358TK3apKxoR2mBDX8hkD1cUePJyzkkNWffsfZEzkExFXN1sNfJoVw161LfQyCuNVDadK", xpub); // Get the "root" address. var address = masterNode.PrivateKey.PubKey.GetAddress(network); // Ensure that the generated address is a City Chain address and not Bitcoin. Assert.Equal("CQtq75vu4bAceku6FmenWBh35i1Y4oskdu", address.ToString()); var publicNode = masterNode.Derive(new KeyPath("m/44'/1926'/0'/0/0")); var changeNode = masterNode.Derive(new KeyPath("m/44'/1926'/0'/1/0")); Assert.Equal("CPtzM2XwLCVS3L6BFK1xYsCcGqgrgsxHrP", publicNode.PrivateKey.PubKey.GetAddress(network).ToString()); Assert.Equal("CY35ZGxzZBYHKyNV4KWKunYLHsTWejVSdR", changeNode.PrivateKey.PubKey.GetAddress(network).ToString()); // Get the first account in the HD wallet, this is same as the level stored in the wallet files. var accountNode = masterNode.Derive(new KeyPath("m/44'/1926'/0'")); var accountExtPubKey = accountNode.Neuter().GetWif(network).ToWif(); Assert.Equal("xpub6BwCLtuvjt6TZ495sJruY1UWPXg6ME9HA92ro75YDHvGpPKY6kQ6ifp6DEszRpJGMtdBvWBaSn4gQDTz4Ctm5m1BMLeFUh3F19mTXA4s3bE", accountExtPubKey); // Create a wallet file. string encryptedSeed = masterNode.PrivateKey.GetEncryptedBitcoinSecret(walletPassword, network).ToWif(); Assert.Equal("6PYW8DRnFZSu3CVC3NfghKFSozZE8gmf76GmsGrrA9ciWbv6F6HhVSKkEQ", encryptedSeed); }
public void ShouldFindUnsedKeyAtTheEndOfFirstChunk() { var filters = new[] { CreateFiltersWith(GetScripts(true, 0, 500)), CreateFiltersWith(GetScripts(true, 500, 499)) }; var unusedKeyIndex = ExtPubKeyExplorer.GetUnusedBech32Keys(1, true, ExtPubKey.GetWif(Network.Main), filters).First().ScriptPubKey.ToCompressedBytes(); Assert.Equal(DerivateScript(true, 999), unusedKeyIndex); }
public void ShouldFindUnsedKeyFirstChunk() { var filters = new[] { CreateFiltersWith(GetScripts(false, 0, 10)), CreateFiltersWith(GetScripts(false, 10, 10)) }; var unusedKeyIndex = ExtPubKeyExplorer.GetUnusedBech32Keys(1, false, ExtPubKey.GetWif(Network.Main), filters).First().ScriptPubKey.ToCompressedBytes(); Assert.Equal(DerivateScript(false, 20), unusedKeyIndex); }
public void ShouldFindNeverUsedKey() { var filters = new[] { FilterModel.FromLine($"0:000000000000de90e633e1b1330859842795d39018d033044e8b003e8cbf58e4:050a2f58828c9820642769ae320a40:{uint256.One}:{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}") }; var unusedKeyIndex = ExtPubKeyExplorer.GetUnusedBech32Keys(1, true, ExtPubKey.GetWif(Network.Main), filters).First().ScriptPubKey.ToCompressedBytes(); Assert.Equal(DerivateScript(true, 0), unusedKeyIndex); }
public void ShouldFindUnsedKeyAnywhereFirstChunk() { var filters = new[] { CreateFiltersWith(GetScripts(true, 0, 1)), CreateFiltersWith(GetScripts(true, 0, 2)), CreateFiltersWith(GetScripts(true, 0, 27)), CreateFiltersWith(GetScripts(true, 27, 3)), }; var unusedKeyIndex = ExtPubKeyExplorer.GetUnusedBech32Keys(1, true, ExtPubKey.GetWif(Network.Main), filters).First().ScriptPubKey.ToCompressedBytes(); Assert.Equal(DerivateScript(true, 30), unusedKeyIndex); }
/// <summary> /// Describe ext public key /// </summary> /// <param name="extPubKey"></param> /// <param name="network"></param> /// <param name="keyPath">The root of the keypath to follow</param> /// <returns></returns> public static ScanTxoutPubkey ExtPubKey(ExtPubKey extPubKey, Network network, KeyPath keyPath) { if (extPubKey == null) { throw new ArgumentNullException(nameof(extPubKey)); } if (network == null) { throw new ArgumentNullException(nameof(network)); } return(ExtPubKey(extPubKey.GetWif(network), keyPath)); }
public static BitcoinExtPubKey BetterParseExtPubKey(string extPubKeyString, Network network, bool ignoreInvalidNetwork) { extPubKeyString = Guard.NotNullOrEmptyOrWhitespace(nameof(extPubKeyString), extPubKeyString, trim: true); ExtPubKey epk; try { epk = ExtPubKey.Parse(extPubKeyString, network); // Starts with "ExtPubKey": "xpub... } catch { try { // Try hex, Old wallet format was like this. epk = new ExtPubKey(ByteHelpers.FromHex(extPubKeyString)); // Starts with "ExtPubKey": "hexbytes... } catch when(ignoreInvalidNetwork) { // Let's replace the version prefix var data = Encoders.Base58Check.DecodeData(extPubKeyString); var versionBytes = network.GetVersionBytes(Base58Type.EXT_PUBLIC_KEY, true); if (versionBytes.Length > data.Length) { throw; } for (int i = 0; i < versionBytes.Length; i++) { data[i] = versionBytes[i]; } extPubKeyString = Encoders.Base58Check.EncodeData(data); epk = ExtPubKey.Parse(extPubKeyString, network); } } return(epk.GetWif(network)); }
/// <summary> /// Create a single signature derivation strategy from public key /// </summary> /// <param name="publicKey">The public key of the wallet</param> /// <param name="options">Derivation options</param> /// <returns></returns> public DerivationStrategyBase CreateDirectDerivationStrategy(ExtPubKey publicKey, DerivationStrategyOptions options = null) { return(CreateDirectDerivationStrategy(publicKey.GetWif(Network), options)); }
/// <inheritdoc /> public override void WriteJson(JsonWriter writer, ExtPubKey?value, JsonSerializer serializer) { var xpub = value?.GetWif(Network.Main).ToWif() ?? throw new ArgumentNullException(nameof(value)); writer.WriteValue(xpub); }