public void TestStorage() { var temp = new FileInfo(Path.GetTempFileName()); try { Console.WriteLine(temp.FullName); var networkParams = NetworkParameters.UnitTests(); var to = new EcKey().ToAddress(networkParams); StoredBlock b1; using (var store = new BoundedOverheadBlockStore(networkParams, temp)) { // Check the first block in a new store is the genesis block. var genesis = store.GetChainHead(); Assert.AreEqual(networkParams.GenesisBlock, genesis.Header); // Build a new block. b1 = genesis.Build(genesis.Header.CreateNextBlock(to).CloneAsHeader()); store.Put(b1); store.SetChainHead(b1); } // Check we can get it back out again if we rebuild the store object. using (var store = new BoundedOverheadBlockStore(networkParams, temp)) { var b2 = store.Get(b1.Header.Hash); Assert.AreEqual(b1, b2); // Check the chain head was stored correctly also. Assert.AreEqual(b1, store.GetChainHead()); } } finally { temp.Delete(); } }
public static EcKey CreateEcKeyFromHexString(String privateKey) { BigInteger pkey = new BigInteger(privateKey, 16); EcKey key = new EcKey(pkey); return(key); }
public void Bounce() { // This test covers bug 64 (False double spends). Check that if we create a spend and it's immediately sent // back to us, this isn't considered as a double spend. var coin1 = Utils.ToNanoCoins(1, 0); var coinHalf = Utils.ToNanoCoins(0, 50); // Start by giving us 1 coin. var inbound1 = TestUtils.CreateFakeTx(_params, coin1, _myAddress); _wallet.Receive(inbound1, null, BlockChain.NewBlockType.BestChain); // Send half to some other guy. Sending only half then waiting for a confirm is important to ensure the tx is // in the unspent pool, not pending or spent. Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Unspent)); Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.All)); var someOtherGuy = new EcKey().ToAddress(_params); var outbound1 = _wallet.CreateSend(someOtherGuy, coinHalf); _wallet.ConfirmSend(outbound1); _wallet.Receive(outbound1, null, BlockChain.NewBlockType.BestChain); // That other guy gives us the coins right back. var inbound2 = new Transaction(_params); inbound2.AddOutput(new TransactionOutput(_params, inbound2, coinHalf, _myAddress)); inbound2.AddInput(outbound1.Outputs[0]); _wallet.Receive(inbound2, null, BlockChain.NewBlockType.BestChain); Assert.AreEqual(coin1, _wallet.GetBalance()); }
public void TestDoubleSpendOnFork() { // Check what happens when a re-org happens and one of our confirmed transactions becomes invalidated by a // double spend on the new best chain. var eventCalled = false; _wallet.DeadTransaction += (sender, e) => eventCalled = true; var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo); _chain.Add(b1); var t1 = _wallet.CreateSend(_someOtherGuy, Utils.ToNanoCoins(10, 0)); var yetAnotherGuy = new EcKey().ToAddress(_unitTestParams); var t2 = _wallet.CreateSend(yetAnotherGuy, Utils.ToNanoCoins(20, 0)); _wallet.ConfirmSend(t1); // Receive t1 as confirmed by the network. var b2 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); b2.AddTransaction(t1); b2.Solve(); _chain.Add(b2); // Now we make a double spend become active after a re-org. var b3 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); b3.AddTransaction(t2); b3.Solve(); _chain.Add(b3); // Side chain. var b4 = b3.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); _chain.Add(b4); // New best chain. // Should have seen a double spend. Assert.IsTrue(eventCalled); Assert.AreEqual(Utils.ToNanoCoins(30, 0), _wallet.GetBalance()); }
public void BasicSpending() { // We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change. var v1 = Utils.ToNanoCoins(1, 0); var t1 = TestUtils.CreateFakeTx(_params, v1, _myAddress); _wallet.Receive(t1, null, BlockChain.NewBlockType.BestChain); Assert.AreEqual(v1, _wallet.GetBalance()); Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Unspent)); Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.All)); var k2 = new EcKey(); var v2 = Utils.ToNanoCoins(0, 50); var t2 = _wallet.CreateSend(k2.ToAddress(_params), v2); Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Unspent)); Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.All)); // Do some basic sanity checks. Assert.AreEqual(1, t2.Inputs.Count); Assert.AreEqual(_myAddress, t2.Inputs[0].ScriptSig.FromAddress); // We have NOT proven that the signature is correct! _wallet.ConfirmSend(t2); Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Pending)); Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Spent)); Assert.AreEqual(2, _wallet.GetPoolSize(Wallet.Pool.All)); }
public void TestForking3() { // Check that we can handle our own spends being rolled back by a fork. var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo); _chain.Add(b1); Assert.AreEqual("50.00", Utils.BitcoinValueToFriendlyString(_wallet.GetBalance())); var dest = new EcKey().ToAddress(_unitTestParams); var spend = _wallet.CreateSend(dest, Utils.ToNanoCoins(10, 0)); _wallet.ConfirmSend(spend); // Waiting for confirmation ... Assert.AreEqual(0UL, _wallet.GetBalance()); var b2 = b1.CreateNextBlock(_someOtherGuy); b2.AddTransaction(spend); b2.Solve(); _chain.Add(b2); Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance()); // genesis -> b1 (receive coins) -> b2 (spend coins) // \-> b3 -> b4 var b3 = b1.CreateNextBlock(_someOtherGuy); var b4 = b3.CreateNextBlock(_someOtherGuy); _chain.Add(b3); _chain.Add(b4); // b4 causes a re-org that should make our spend go inactive. Because the inputs are already spent our // available balance drops to zero again. Assert.AreEqual(0UL, _wallet.GetBalance(Wallet.BalanceType.Available)); // We estimate that it'll make it back into the block chain (we know we won't double spend). // assertEquals(Utils.toNanoCoins(40, 0), wallet.getBalance(Wallet.BalanceType.ESTIMATED)); }
public void TestAsn1Roundtrip() { var privKeyAsn1 = Hex.Decode("3082011302010104205c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4aa081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a144034200042af7a2aafe8dafd7dc7f9cfb58ce09bda7dce28653ab229b98d1d3d759660c672dd0db18c8c2d76aa470448e876fc2089ab1354c01a6e72cefc50915f4a963ee"); var decodedKey = EcKey.FromAsn1(privKeyAsn1); // Now re-encode and decode the ASN.1 to see if it is equivalent (it does not produce the exact same byte // sequence, some integers are padded now). var roundtripKey = EcKey.FromAsn1(decodedKey.ToAsn1()); byte[] message; foreach (var key in new[] { decodedKey, roundtripKey }) { message = Utils.ReverseBytes(Hex.Decode("11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a")); var output = key.Sign(message); Assert.IsTrue(key.Verify(message, output)); output = Hex.Decode("304502206faa2ebc614bf4a0b31f0ce4ed9012eb193302ec2bcaccc7ae8bb40577f47549022100c73a1a1acc209f3f860bf9b9f5e13e9433db6f8b7bd527a088a0e0cd0a4c83e9"); Assert.IsTrue(key.Verify(message, output)); } // Try to sign with one key and verify with the other. message = Utils.ReverseBytes(Hex.Decode("11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a")); Assert.IsTrue(roundtripKey.Verify(message, decodedKey.Sign(message))); Assert.IsTrue(decodedKey.Verify(message, roundtripKey.Sign(message))); }
public void TestStorage() { var temp = new FileInfo(Path.GetTempFileName()); try { Console.WriteLine(temp.FullName); var @params = NetworkParameters.UnitTests(); var to = new EcKey().ToAddress(@params); StoredBlock b1; using (var store = new BoundedOverheadBlockStore(@params, temp)) { // Check the first block in a new store is the genesis block. var genesis = store.GetChainHead(); Assert.AreEqual(@params.GenesisBlock, genesis.Header); // Build a new block. b1 = genesis.Build(genesis.Header.CreateNextBlock(to).CloneAsHeader()); store.Put(b1); store.SetChainHead(b1); } // Check we can get it back out again if we rebuild the store object. using (var store = new BoundedOverheadBlockStore(@params, temp)) { var b2 = store.Get(b1.Header.Hash); Assert.AreEqual(b1, b2); // Check the chain head was stored correctly also. Assert.AreEqual(b1, store.GetChainHead()); } } finally { temp.Delete(); } }
public void TestForking4() { // Check that we can handle external spends on an inactive chain becoming active. An external spend is where // we see a transaction that spends our own coins but we did not broadcast it ourselves. This happens when // keys are being shared between wallets. var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo); _chain.Add(b1); Assert.AreEqual("50.00", Utils.BitcoinValueToFriendlyString(_wallet.GetBalance())); var dest = new EcKey().ToAddress(_unitTestParams); var spend = _wallet.CreateSend(dest, Utils.ToNanoCoins(50, 0)); // We do NOT confirm the spend here. That means it's not considered to be pending because createSend is // stateless. For our purposes it is as if some other program with our keys created the tx. // // genesis -> b1 (receive 50) --> b2 // \-> b3 (external spend) -> b4 var b2 = b1.CreateNextBlock(_someOtherGuy); _chain.Add(b2); var b3 = b1.CreateNextBlock(_someOtherGuy); b3.AddTransaction(spend); b3.Solve(); _chain.Add(b3); // The external spend is not active yet. Assert.AreEqual(Utils.ToNanoCoins(50, 0), _wallet.GetBalance()); var b4 = b3.CreateNextBlock(_someOtherGuy); _chain.Add(b4); // The external spend is now active. Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance()); }
public void SetUp() { var myKey = new EcKey(); _myAddress = myKey.ToAddress(_params); _wallet = new Wallet(_params); _wallet.AddKey(myKey); _blockStore = new MemoryBlockStore(_params); }
/// <summary> /// Creates a scriptSig that can redeem a pay-to-address output. /// If given signature is null, incomplete scriptSig will be created with ScriptOpCodes.OP_0 instead of signature /// </summary> public static Script CreateInputScript(TransactionSignature signature, EcKey pubKey) { byte[] pubkeyBytes = pubKey.PublicKeyBytes; byte[] sigBytes = signature != null?signature.EncodeToBitcoin() : new byte[] { }; return(new ScriptBuilder().Data(sigBytes).Data(pubkeyBytes).Build()); }
public static void SaveEcKey(EcKey ecKey) { byte[] bytes = ecKey.ToAsn1(); FileStream fs = new FileStream(PRIV_KEY_FILENAME, FileMode.Create, FileAccess.Write); fs.Write(bytes, 0, bytes.Length); fs.Close(); }
private static EcKey CreateRandomKey(string curve, string defaultAlgo) { var kid = new Guid().ToString("N"); var key = new EcKey(kid, curve); Assert.Equal(kid, key.Kid); Assert.Equal(defaultAlgo, key.DefaultSignatureAlgorithm); return(key); }
private static EcKey CreateKeyFromJwk(string json, string curve, string defaultAlgo, bool isPrivateKey = false) { var jwk = JsonConvert.DeserializeObject <JsonWebKey>(json); var kid = new Guid().ToString("N"); var key = new EcKey(kid, curve, jwk.X, jwk.Y, isPrivateKey ? jwk.D : null); Assert.Equal(kid, key.Kid); Assert.Equal(defaultAlgo, key.DefaultSignatureAlgorithm); return(key); }
public static EcKey LoadEcKey() { using (FileStream fs = File.OpenRead(PRIV_KEY_FILENAME)) { byte[] b = new byte[1024]; fs.Read(b, 0, b.Length); EcKey key = EcKey.FromAsn1(b); return(key); } }
public void Base58EncodingStress() { // Replace the loop bound with 1000 to get some keys with leading zero byte for (var i = 0; i < 20; i++) { var key = new EcKey(); var key1 = new DumpedPrivateKey(NetworkParameters.TestNet(), key.GetPrivateKeyEncoded(NetworkParameters.TestNet()).ToString()).Key; Assert.AreEqual(Utils.BytesToHexString(key.GetPrivKeyBytes()), Utils.BytesToHexString(key1.GetPrivKeyBytes())); } }
public IAsymmetricKeyPair CreateKeyPair(string curve) { AsymmetricCipherKeyPair keyPair = keyPairGenerator.GenerateEcKeyPair(curve); byte[] publicKeyContent = GetPublicKey(keyPair.Public); byte[] privateKeyContent = GetPrivateKey(keyPair.Private); var publicKey = new EcKey(publicKeyContent, AsymmetricKeyType.Public, GetKeyLength(keyPair.Public), curve); var privateKey = new EcKey(privateKeyContent, AsymmetricKeyType.Private, GetKeyLength(keyPair.Private), curve); return(new AsymmetricKeyPair(privateKey, publicKey)); }
public static void Run(string[] args) { // TODO: Assumes production network not testnet. Make it selectable. var @params = NetworkParameters.ProdNet(); try { // Decode the private key from Satoshi's Base58 variant. If 51 characters long then it's from BitCoins // "dumpprivkey" command and includes a version byte and checksum. Otherwise assume it's a raw key. EcKey key; if (args[0].Length == 51) { var dumpedPrivateKey = new DumpedPrivateKey(@params, args[0]); key = dumpedPrivateKey.Key; } else { var privKey = Base58.DecodeToBigInteger(args[0]); key = new EcKey(privKey); } Console.WriteLine("Address from private key is: " + key.ToAddress(@params)); // And the address ... var destination = new Address(@params, args[1]); // Import the private key to a fresh wallet. var wallet = new Wallet(@params); wallet.AddKey(key); // Find the transactions that involve those coins. using (var blockStore = new MemoryBlockStore(@params)) { var chain = new BlockChain(@params, wallet, blockStore); var peerGroup = new PeerGroup(blockStore, @params, chain); peerGroup.AddAddress(new PeerAddress(IPAddress.Loopback)); peerGroup.Start(); peerGroup.DownloadBlockChain(); peerGroup.Stop(); // And take them! Console.WriteLine("Claiming " + Utils.BitcoinValueToFriendlyString(wallet.GetBalance()) + " coins"); wallet.SendCoins(peerGroup, destination, wallet.GetBalance()); // Wait a few seconds to let the packets flush out to the network (ugly). Thread.Sleep(5000); } } catch (IndexOutOfRangeException) { Console.WriteLine("First arg should be private key in Base58 format. Second argument should be address to send to."); } }
public static void Run(string[] args) { // TODO: Assumes production network not testnet. Make it selectable. var networkParams = NetworkParameters.ProdNet(); try { // Decode the private key from Satoshi's Base58 variant. If 51 characters long then it's from BitCoins // "dumpprivkey" command and includes a version byte and checksum. Otherwise assume it's a raw key. EcKey key; if (args[0].Length == 51) { var dumpedPrivateKey = new DumpedPrivateKey(networkParams, args[0]); key = dumpedPrivateKey.Key; } else { var privKey = Base58.DecodeToBigInteger(args[0]); key = new EcKey(privKey); } Console.WriteLine("Address from private key is: " + key.ToAddress(networkParams)); // And the address ... var destination = new Address(networkParams, args[1]); // Import the private key to a fresh wallet. var wallet = new Wallet(networkParams); wallet.AddKey(key); // Find the transactions that involve those coins. using (var blockStore = new MemoryBlockStore(networkParams)) { var chain = new BlockChain(networkParams, wallet, blockStore); var peerGroup = new PeerGroup(blockStore, networkParams, chain); peerGroup.AddAddress(new PeerAddress(IPAddress.Loopback)); peerGroup.Start(); peerGroup.DownloadBlockChain(); peerGroup.Stop(); // And take them! Console.WriteLine("Claiming " + Utils.BitcoinValueToFriendlystring(wallet.GetBalance()) + " coins"); wallet.SendCoins(peerGroup, destination, wallet.GetBalance()); // Wait a few seconds to let the packets flush out to the network (ugly). Thread.Sleep(5000); } } catch (IndexOutOfRangeException) { Console.WriteLine("First arg should be private key in Base58 format. Second argument should be address to send to."); } }
public void TestSignatures() { // Test that we can construct an ECKey from a private key (deriving the public from the private), then signing // a message with it. var privkey = new BigInteger(1, Hex.Decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19")); var key = new EcKey(privkey); var message = new byte[32]; // All zeroes. var output = key.Sign(message); Assert.True(key.Verify(message, output)); // Test interop with a signature from elsewhere. var sig = Hex.Decode("3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d"); Assert.True(key.Verify(message, sig)); }
/// <summary> /// Constructor for use if the keys and SIN were derived external to this library. /// </summary> /// <param name="ecKey">An elliptical curve key.</param> /// <param name="clientName">The label for this client.</param> /// <param name="envUrl">The target server URL.</param> public BitPayService(EcKey ecKey, string clientName = BITPAY_PLUGIN_INFO, string envUrl = BITPAY_URL) { _ecKey = ecKey; _identity = KeyUtils.DeriveSIN(_ecKey); _baseUrl = envUrl; _httpClient = new HttpClient { BaseAddress = new Uri(_baseUrl) }; _tokenCache = new Dictionary <string, string>(); var response = Get <List <Dictionary <string, string> > >("tokens", new Dictionary <string, string>()); _tokenCache = response.SelectMany(t => t).ToDictionary(r => r.Key, r => r.Value); }
public BitPayTest() { // string privHexStr = "00c7a830ce41ea2f0955016b74e213da3b4ecb1fe3aaf3ea51191925f337d7f8cb"; string privHexStr = "c7a830ce41ea2f0955016b74e213da3b4ecb1fe3aaf3ea51191925f337d7f8cb"; byte[] bytes = KeyUtils.hexToBytes(privHexStr); BigInteger pkey = new BigInteger(privHexStr, 16); _ecKey = KeyUtils.createEcKeyFromHexString(privHexStr); string privHexStr2 = "c7a830ce41ea2f0955016b74e213da3b4ecb1fe3aaf3ea51191925f337d7f8cb"; byte[] bytes2 = KeyUtils.hexToBytes(privHexStr2); _nbKey = new Key(bytes2, -1, false); }
public void TestSignatures() { // Test that we can construct an ECKey from a private key (deriving the public from the private), then signing // a message with it. var privkey = new BigInteger(1, Hex.Decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19")); var key = new EcKey(privkey); var message = new byte[32]; // All zeroes. var output = key.Sign(message); Assert.IsTrue(key.Verify(message, output)); // Test interop with a signature from elsewhere. var sig = Hex.Decode("3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d"); Assert.IsTrue(key.Verify(message, sig)); }
private Dictionary <string, string> _tokenCache; // {facade, token} /// <summary> /// Constructor for use if the keys and SIN are managed by this library. /// </summary> /// <param name="keyString">Private key string.</param> /// <param name="clientName">The label for this client.</param> /// <param name="envUrl">The target server URL.</param> public BitPayService(string keyString = "", string clientName = BITPAY_PLUGIN_INFO, string envUrl = BITPAY_URL) { if (clientName.Equals(BITPAY_PLUGIN_INFO)) { clientName += " on " + Environment.MachineName; } // Eliminate special characters from the client name (used as a token label). Trim to 60 chars. string _clientName = new Regex("[^a-zA-Z0-9_ ]").Replace(clientName, "_"); if (_clientName.Length > 60) { _clientName = _clientName.Substring(0, 60); } _baseUrl = envUrl; _httpClient = new HttpClient() { BaseAddress = new Uri(_baseUrl) }; if (!String.IsNullOrWhiteSpace(keyString)) { _ecKey = KeyUtils.CreateEcKeyFromHexString(keyString); } else { if (KeyUtils.PrivateKeyExists()) { _ecKey = KeyUtils.LoadEcKey(); } else { _ecKey = KeyUtils.CreateEcKey(); KeyUtils.SaveEcKey(_ecKey); } } _identity = KeyUtils.DeriveSIN(_ecKey); _tokenCache = new Dictionary <string, string>(); var response = Get <List <Dictionary <string, string> > >("tokens", new Dictionary <string, string>()); _tokenCache = response.SelectMany(t => t).ToDictionary(r => r.Key, r => r.Value); }
public static String DeriveSIN(EcKey ecKey) { String preSIN = "0F02" + BytesToHex(ecKey.PubKeyHash); // Convert the hex string back to binary and double sha256 hash it leaving in binary both times byte[] preSINbyte = HexToBytes(preSIN); byte[] hash2Bytes = Utils.DoubleDigest(preSINbyte); // Convert back to hex and take first four bytes String hashString = BytesToHex(hash2Bytes); String first4Bytes = hashString.Substring(0, 8); // Append first four bytes to fully appended SIN string String unencoded = preSIN + first4Bytes; byte[] unencodedBytes = new BigInteger(unencoded, 16).ToByteArray(); String encoded = Base58.Encode(unencodedBytes); return(encoded); }
private static void DoSignVerifyTests(int digestSize, EcKey privateKey, EcKey publicKey) { // Create pseudo-random hash. var rnd = new Random(0); var digest = new byte[digestSize]; rnd.NextBytes(digest); bool verified; // Check if private key can sign digest. var signatureResult = privateKey.SignAsync(digest, null).Result; var signature = signatureResult.Item1; var algorithm = signatureResult.Item2; Assert.Equal(algorithm, privateKey.DefaultSignatureAlgorithm); // Check if private key can verify digest. verified = privateKey.VerifyAsync(digest, signature, algorithm).Result; Assert.True(verified); if (publicKey != null) { // Check if public key can verify digest. verified = publicKey.VerifyAsync(digest, signature, algorithm).Result; Assert.True(verified); } signature[signature.Length - 1] ^= 1; // Check if private key can deny invalid digest. verified = privateKey.VerifyAsync(digest, signature, algorithm).Result; Assert.False(verified); if (publicKey != null) { // Check if public key can deny invalid digest. verified = publicKey.VerifyAsync(digest, signature, algorithm).Result; Assert.False(verified); } }
public void Transactions() { // This test covers a bug in which Transaction.getValueSentFromMe was calculating incorrectly. var tx = TestUtils.CreateFakeTx(_params, Utils.ToNanoCoins(1, 0), _myAddress); // Now add another output (ie, change) that goes to some other address. var someOtherGuy = new EcKey().ToAddress(_params); var output = new TransactionOutput(_params, tx, Utils.ToNanoCoins(0, 5), someOtherGuy); tx.AddOutput(output); // Note that tx is no longer valid: it spends more than it imports. However checking transactions balance // correctly isn't possible in SPV mode because value is a property of outputs not inputs. Without all // transactions you can't check they add up. _wallet.Receive(tx, null, BlockChain.NewBlockType.BestChain); // Now the other guy creates a transaction which spends that change. var tx2 = new Transaction(_params); tx2.AddInput(output); tx2.AddOutput(new TransactionOutput(_params, tx2, Utils.ToNanoCoins(0, 5), _myAddress)); // tx2 doesn't send any coins from us, even though the output is in the wallet. Assert.AreEqual(Utils.ToNanoCoins(0, 0), tx2.GetValueSentFromMe(_wallet)); }
/// <summary> /// Creates an incomplete scriptSig that, once filled with signatures, can redeem output containing this scriptPubKey. /// Instead of the signatures resulting script has ScriptOpCodes.OP_0. /// Having incomplete input script allows to pass around partially signed tx. /// It is expected that this program later on will be updated with proper signatures. /// </summary> public Script CreateEmptyInputScript(EcKey key, Script redeemScript) { if (this.IsSentToAddress()) { Guard.Require(key != null, "Key required to create pay-to-address input script"); return(ScriptBuilder.CreateInputScript(null, key)); } if (this.IsSentToRawPubKey()) { return(ScriptBuilder.CreateInputScript(null)); } if (this.IsPayToScriptHash()) { throw new NotImplementedException(); ////Guard.Require(redeemScript != null, "Redeem script required to create P2SH input script"); ////return ScriptBuilder.CreateP2SHMultiSigInputScript(null, redeemScript); } throw new ScriptException("Do not understand script type: " + this); }
public static String Sign(EcKey ecKey, String input) { String hash = Sha256Hash(input); return(BytesToHex(ecKey.Sign(HexToBytes(hash)))); }
public void TestBasicSpending() { // We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change. var v1 = Utils.ToNanoCoins(1, 0); var t1 = CreateFakeTx(v1, _myAddress); _wallet.Receive(t1, null, BlockChain.NewBlockType.BestChain); Assert.AreEqual(v1, _wallet.GetBalance()); var k2 = new EcKey(); var v2 = Utils.ToNanoCoins(0, 50); var t2 = _wallet.CreateSend(k2.ToAddress(_params), v2); // Do some basic sanity checks. Assert.AreEqual(1, t2.Inputs.Count); Assert.AreEqual(_myAddress, t2.Inputs[0].ScriptSig.FromAddress); // We have NOT proven that the signature is correct! }
public void TestDoubleSpendOnForkPending() { // Check what happens when a re-org happens and one of our UNconfirmed transactions becomes invalidated by a // double spend on the new best chain. Transaction eventDead = null; Transaction eventReplacement = null; _wallet.DeadTransaction += (sender, e) => { eventDead = e.DeadTx; eventReplacement = e.ReplacementTx; }; // Start with 50 coins. var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo); _chain.Add(b1); var t1 = _wallet.CreateSend(_someOtherGuy, Utils.ToNanoCoins(10, 0)); var yetAnotherGuy = new EcKey().ToAddress(_unitTestParams); var t2 = _wallet.CreateSend(yetAnotherGuy, Utils.ToNanoCoins(20, 0)); _wallet.ConfirmSend(t1); // t1 is still pending ... var b2 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); _chain.Add(b2); Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance()); Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated)); // Now we make a double spend become active after a re-org. // genesis -> b1 -> b2 [t1 pending] // \-> b3 (t2) -> b4 var b3 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); b3.AddTransaction(t2); b3.Solve(); _chain.Add(b3); // Side chain. var b4 = b3.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); _chain.Add(b4); // New best chain. // Should have seen a double spend against the pending pool. Assert.AreEqual(t1, eventDead); Assert.AreEqual(t2, eventReplacement); Assert.AreEqual(Utils.ToNanoCoins(30, 0), _wallet.GetBalance()); // ... and back to our own parallel universe. var b5 = b2.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); _chain.Add(b5); var b6 = b5.CreateNextBlock(new EcKey().ToAddress(_unitTestParams)); _chain.Add(b6); // genesis -> b1 -> b2 -> b5 -> b6 [t1 pending] // \-> b3 [t2 inactive] -> b4 Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance()); Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated)); }
/// <summary> /// Creates a script that sends coins directly to the given public key. Same as /// <seealso cref="Script#CreateOutputScript(byte[])"/> but more type safe. /// </summary> public static byte[] CreateOutputScript(EcKey pubkey) { return(CreateOutputScript(pubkey.PubKey)); }
/// <summary> /// Creates a script that sends coins directly to the given public key. Same as /// <seealso cref="Script#CreateOutputScript(byte[])"/> but more type safe. /// </summary> public static byte[] CreateOutputScript(EcKey pubkey) { return CreateOutputScript(pubkey.PubKey); }
public TransactionSignature CalculateSignature(Transaction transaction, TransactionOutPoint outPoint, EcKey key, Script.Script redeemScript, Transaction.SigHash hashType) { // at the moment only signing all the outputs is supported Thrower.If(hashType != Transaction.SigHash.All).Throw <TransactionException>("Only SigHash type 'All' supported"); //// clone the transaction and clear all the inputs //// only the inputs for the equivalent output needs to be present for signing var signTx = transaction.Clone(); signTx.Inputs.ForEach(input => input.ScriptBytes = Enumerable.Empty <byte>().ToArray()); // set the redeem script and clear it of 'OP_CODESEPARATOR' var connectedScript = redeemScript.GetProgram(); var redeemConnectedScript = Script.Script.RemoveAllInstancesOfOp(connectedScript, ScriptOpCodes.OP_CODESEPARATOR); signTx.FindInput(outPoint).ScriptBytes = redeemConnectedScript; // serialize then hash the transaction to HEX and sign it. var trxHex = this.Serializer.ToHex(signTx, hashType); var hash = CryptoUtil.Sha256HashTwice(CryptoUtil.ConvertHex(trxHex)); return(new TransactionSignature(key.Sign(hash), hashType)); }
private static void GenerateKeyPair(EcKey ecKey) { Console.Clear(); DrawTitle(); if (env == Env.Test) { ecKeyFilePath = appConfig.BitPayConfiguration.EnvConfig.Test.PrivateKeyPath; } if (env == Env.Prod) { ecKeyFilePath = appConfig.BitPayConfiguration.EnvConfig.Prod.PrivateKeyPath; } if (!string.IsNullOrEmpty(ecKeyFilePath)) { Console.WriteLine(" The current private key file defined is: " + ecKeyFilePath); Console.WriteLine(" Would you like to change it? [yes|no] (default: no)"); Console.WriteLine(); Console.Write(" > "); var answer = Console.ReadLine(); while (answer.ToLower() != "yes" && answer.ToLower() != "no" && answer.ToLower() != "") { answer = Console.ReadLine(); } if (answer.ToLower() == "no" || answer.ToLower() == "") { if (File.Exists(ecKeyFilePath)) { SetNotification(" Selected private key file: " + ecKeyFilePath); return; } SetNotification(" The private key file does not longer exists in: \n \"" + ecKeyFilePath + "\"\n Please, proceed with the following instructions."); Console.Clear(); DrawTitle(); } } Console.WriteLine(" Enter the full path for the private key files where this will loaded from or generated:"); Console.WriteLine(" If click Enter, a file named \"bitpay_private_" + env.ToLower() + " will be generated in the root of this application and"); Console.WriteLine(" any file with the same name in this directory will be overwritten."); Console.WriteLine(); Console.Write(" > "); var newEcKeyPath = Console.ReadLine().Trim(); if (string.IsNullOrEmpty(newEcKeyPath)) { ecKeyFilePath = @"bitpay_private_" + env.ToLower() + ".key"; if (KeyUtils.PrivateKeyExists(ecKeyFilePath)) { SetNotification(" The file name entered already exists: \n \"" + ecKeyFilePath + "\"\n Make sure you want to modify it and then delete it before trying again"); return; } ecKey = KeyUtils.CreateEcKey(); KeyUtils.SaveEcKey(ecKey); SetNotification(" New private key generated successfully with public key:\n " + ecKey.PublicKeyHexBytes + "\n in: \"" + ecKeyFilePath + "\""); } else { if (!File.Exists(newEcKeyPath)) { SetNotification(" The file entered not found in: \n \"" + newEcKeyPath + "\""); Console.Clear(); DrawTitle(); Console.WriteLine(" Would you like to provide a different file path? [yes|no] (default: no)"); Console.WriteLine( " If 'no', a new file will be generated in the entered location with the given name."); Console.WriteLine(); Console.Write(" > "); var answer = Console.ReadLine(); while (answer.ToLower() != "yes" && answer.ToLower() != "no" && answer.ToLower() != "") { answer = Console.ReadLine(); } if (answer.ToLower() == "yes") { GenerateKeyPair(ecKey); } if (KeyUtils.PrivateKeyExists(newEcKeyPath)) { SetNotification(" The file name entered already exists: \n \"" + newEcKeyPath + "\"\n Be sure you want to modify it and then delete it manually before trying again"); return; } ecKeyFilePath = newEcKeyPath; } try { ecKey = KeyUtils.CreateEcKey(); KeyUtils.SaveEcKey(ecKey); } catch (Exception e) { SetNotification( " An error occurred, please, check if the you have the right\n permissions to write in the specified directory.\n Error Details: " + e.Message); return; } SetNotification(" New key pair generated successfully with public key: " + ecKey.PublicKeyHexBytes + " in: \n \"" + newEcKeyPath + "\""); } if (env == Env.Test) { appConfig.BitPayConfiguration.EnvConfig.Test.PrivateKeyPath = ecKeyFilePath; } if (env == Env.Prod) { appConfig.BitPayConfiguration.EnvConfig.Prod.PrivateKeyPath = ecKeyFilePath; } GenerateConfFile(confFilePath); }
/// <summary> /// Once a transaction has some inputs and outputs added, the signatures in the inputs can be calculated. The /// signature is over the transaction itself, to prove the redeemer actually created that transaction, /// so we have to do this step last. /// </summary> /// <remarks> /// This method is similar to SignatureHash in script.cpp /// </remarks> /// <param name="hashType">This should always be set to SigHash.ALL currently. Other types are unused. </param> /// <param name="defaultWallet">A wallet is required to fetch the keys needed for signing.</param> /// <exception cref="ScriptException"/> public void SignInputs(SigHash hashType, IDefaultWallet defaultWallet) { Debug.Assert(_transactionInputs.Count > 0); Debug.Assert(_transactionOutputs.Count > 0); // I don't currently have an easy way to test other modes work, as the official client does not use them. Debug.Assert(hashType == SigHash.All); // The transaction is signed with the input scripts empty except for the input we are signing. In the case // where addInput has been used to set up a new transaction, they are already all empty. The input being signed // has to have the connected OUTPUT program in it when the hash is calculated! // // Note that each input may be claiming an output sent to a different key. So we have to look at the outputs // to figure out which key to sign with. var signatures = new byte[_transactionInputs.Count][]; var signingKeys = new EcKey[_transactionInputs.Count]; for (var i = 0; i < _transactionInputs.Count; i++) { var transactionInput = _transactionInputs[i]; Debug.Assert(transactionInput.ScriptBytes.Length == 0, "Attempting to sign a non-fresh transaction"); // Set the input to the script of its output. transactionInput.ScriptBytes = transactionInput.Outpoint.ConnectedPubKeyScript; // Find the signing key we'll need to use. var connectedPublicKeyHash = transactionInput.Outpoint.ConnectedPubKeyHash; var key = defaultWallet.FindKeyFromPublicHash(connectedPublicKeyHash); // This assert should never fire. If it does, it means the wallet is inconsistent. Debug.Assert(key != null, "Transaction exists in wallet that we cannot redeem: " + Utils.BytesToHexString(connectedPublicKeyHash)); // Keep the key around for the script creation step below. signingKeys[i] = key; // The anyoneCanPay feature isn't used at the moment. const bool anyoneCanPay = false; var hash = HashTransactionForSignature(hashType, anyoneCanPay); // Set the script to empty again for the next input. transactionInput.ScriptBytes = TransactionInput.EmptyArray; // Now sign for the output so we can redeem it. We use the keypair to sign the hash, // and then put the resulting signature in the script along with the public key (below). using (var byteOutputStream = new MemoryStream()) { byteOutputStream.Write(key.Sign(hash)); byteOutputStream.Write((byte) (((int) hashType + 1) | (0))); signatures[i] = byteOutputStream.ToArray(); } } // Now we have calculated each signature, go through and create the scripts. Reminder: the script consists of // a signature (over a hash of the transaction) and the complete public key needed to sign for the connected // output. for (var i = 0; i < _transactionInputs.Count; i++) { var transactionInput = _transactionInputs[i]; Debug.Assert(transactionInput.ScriptBytes.Length == 0); var signingKey = signingKeys[i]; transactionInput.ScriptBytes = Script.CreateInputScript(signatures[i], signingKey.PublicKey); } // Every input is now complete. }