Esempio n. 1
0
        public async Task AcceptToMemoryPool_WithMultiInOutValidTxns_IsSuccessfullAsync()
        {
            string dataDir = Path.Combine("TestData", nameof(MempoolValidatorTest), nameof(this.AcceptToMemoryPool_WithMultiInOutValidTxns_IsSuccessfullAsync));

            Directory.CreateDirectory(dataDir);

            BitcoinSecret     miner   = new BitcoinSecret(new Key(), Network.PurpleRegTest);
            ITestChainContext context = await TestChainFactory.CreateAsync(Network.PurpleRegTest, miner.PubKey.Hash.ScriptPubKey, dataDir);

            IMempoolValidator validator = context.MempoolValidator;

            Assert.NotNull(validator);

            BitcoinSecret alice   = new BitcoinSecret(new Key(), Network.PurpleRegTest);
            BitcoinSecret bob     = new BitcoinSecret(new Key(), Network.PurpleRegTest);
            BitcoinSecret satoshi = new BitcoinSecret(new Key(), Network.PurpleRegTest);

            // Fund Alice, Bob, Satoshi
            // 50 Coins come from first tx on chain - send satoshi 1, bob 2, Alice 1.5 and change back to miner
            Coin coin = new Coin(context.SrcTxs[0].GetHash(), 0, context.SrcTxs[0].TotalOut, miner.ScriptPubKey);
            TransactionBuilder txBuilder     = new TransactionBuilder();
            Transaction        multiOutputTx = txBuilder
                                               .AddCoins(new List <Coin> {
                coin
            })
                                               .AddKeys(miner)
                                               .Send(satoshi.GetAddress(), "1.00")
                                               .Send(bob.GetAddress(), "2.00")
                                               .Send(alice.GetAddress(), "1.50")
                                               .SendFees("0.001")
                                               .SetChange(miner.GetAddress())
                                               .BuildTransaction(true);

            Assert.True(txBuilder.Verify(multiOutputTx)); //check fully signed
            MempoolValidationState state = new MempoolValidationState(false);

            Assert.True(await validator.AcceptToMemoryPool(state, multiOutputTx), $"Transaction: {nameof(multiOutputTx)} failed mempool validation.");

            // Alice then Bob sends to Satoshi
            Coin[] aliceCoins = multiOutputTx.Outputs
                                .Where(o => o.ScriptPubKey == alice.ScriptPubKey)
                                .Select(o => new Coin(new OutPoint(multiOutputTx.GetHash(), multiOutputTx.Outputs.IndexOf(o)), o))
                                .ToArray();
            Coin[] bobCoins = multiOutputTx.Outputs
                              .Where(o => o.ScriptPubKey == bob.ScriptPubKey)
                              .Select(o => new Coin(new OutPoint(multiOutputTx.GetHash(), multiOutputTx.Outputs.IndexOf(o)), o))
                              .ToArray();

            txBuilder = new TransactionBuilder();
            Transaction multiInputTx = txBuilder
                                       .AddCoins(aliceCoins)
                                       .AddKeys(alice)
                                       .Send(satoshi.GetAddress(), "0.8")
                                       .SetChange(alice.GetAddress())
                                       .SendFees("0.0005")
                                       .Then()
                                       .AddCoins(bobCoins)
                                       .AddKeys(bob)
                                       .Send(satoshi.GetAddress(), "0.2")
                                       .SetChange(bob.GetAddress())
                                       .SendFees("0.0005")
                                       .BuildTransaction(true);

            Assert.True(txBuilder.Verify(multiInputTx)); //check fully signed
            Assert.True(await validator.AcceptToMemoryPool(state, multiInputTx), $"Transaction: {nameof(multiInputTx)} failed mempool validation.");

            Directory.Delete(dataDir, true);
        }
Esempio n. 2
0
        public async Task AcceptToMemoryPool_WithMultiSigValidTxns_IsSuccessfullAsync()
        {
            string dataDir = Path.Combine("TestData", nameof(MempoolValidatorTest), nameof(this.AcceptToMemoryPool_WithMultiSigValidTxns_IsSuccessfullAsync));

            Directory.CreateDirectory(dataDir);

            BitcoinSecret     miner   = new BitcoinSecret(new Key(), Network.PurpleRegTest);
            ITestChainContext context = await TestChainFactory.CreateAsync(Network.PurpleRegTest, miner.PubKey.Hash.ScriptPubKey, dataDir);

            IMempoolValidator validator = context.MempoolValidator;

            Assert.NotNull(validator);

            BitcoinSecret alice   = new BitcoinSecret(new Key(), Network.PurpleRegTest);
            BitcoinSecret bob     = new BitcoinSecret(new Key(), Network.PurpleRegTest);
            BitcoinSecret satoshi = new BitcoinSecret(new Key(), Network.PurpleRegTest);
            BitcoinSecret nico    = new BitcoinSecret(new Key(), Network.PurpleRegTest);

            // corp needs two out of three of alice, bob, nico
            Script corpMultiSig = PayToMultiSigTemplate
                                  .Instance
                                  .GenerateScriptPubKey(2, new[] { alice.PubKey, bob.PubKey, nico.PubKey });

            // Fund corp
            // 50 Coins come from first tx on chain - send corp 42 and change back to miner
            Coin coin = new Coin(context.SrcTxs[0].GetHash(), 0, context.SrcTxs[0].TotalOut, miner.ScriptPubKey);
            TransactionBuilder txBuilder        = new TransactionBuilder();
            Transaction        sendToMultiSigTx = txBuilder
                                                  .AddCoins(new List <Coin> {
                coin
            })
                                                  .AddKeys(miner)
                                                  .Send(corpMultiSig, "42.00")
                                                  .SendFees("0.001")
                                                  .SetChange(miner.GetAddress())
                                                  .BuildTransaction(true);

            Assert.True(txBuilder.Verify(sendToMultiSigTx)); //check fully signed
            MempoolValidationState state = new MempoolValidationState(false);

            Assert.True(await validator.AcceptToMemoryPool(state, sendToMultiSigTx), $"Transaction: {nameof(sendToMultiSigTx)} failed mempool validation.");

            // AliceBobNico corp. send to Satoshi
            Coin[] corpCoins = sendToMultiSigTx.Outputs
                               .Where(o => o.ScriptPubKey == corpMultiSig)
                               .Select(o => new Coin(new OutPoint(sendToMultiSigTx.GetHash(), sendToMultiSigTx.Outputs.IndexOf(o)), o))
                               .ToArray();

            // Alice initiates the transaction
            txBuilder = new TransactionBuilder();
            Transaction multiSigTx = txBuilder
                                     .AddCoins(corpCoins)
                                     .AddKeys(alice)
                                     .Send(satoshi.GetAddress(), "4.5")
                                     .SendFees("0.001")
                                     .SetChange(corpMultiSig)
                                     .BuildTransaction(true);

            Assert.True(!txBuilder.Verify(multiSigTx)); //Well, only one signature on the two required...

            // Nico completes the transaction
            txBuilder  = new TransactionBuilder();
            multiSigTx = txBuilder
                         .AddCoins(corpCoins)
                         .AddKeys(nico)
                         .SignTransaction(multiSigTx);
            Assert.True(txBuilder.Verify(multiSigTx));

            Assert.True(await validator.AcceptToMemoryPool(state, multiSigTx), $"Transaction: {nameof(multiSigTx)} failed mempool validation.");

            Directory.Delete(dataDir, true);
        }
Esempio n. 3
0
        public async Task AcceptToMemoryPool_WithP2SHValidTxns_IsSuccessfullAsync()
        {
            string dataDir = GetTestDirectoryPath(this);

            var miner = new BitcoinSecret(new Key(), Network.RegTest);
            ITestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, miner.PubKey.Hash.ScriptPubKey, dataDir);

            IMempoolValidator validator = context.MempoolValidator;

            Assert.NotNull(validator);

            var alice   = new BitcoinSecret(new Key(), Network.RegTest);
            var bob     = new BitcoinSecret(new Key(), Network.RegTest);
            var satoshi = new BitcoinSecret(new Key(), Network.RegTest);
            var nico    = new BitcoinSecret(new Key(), Network.RegTest);

            // corp needs two out of three of alice, bob, nico
            Script corpMultiSig = PayToMultiSigTemplate
                                  .Instance
                                  .GenerateScriptPubKey(2, new[] { alice.PubKey, bob.PubKey, nico.PubKey });

            // P2SH address for corp multi-sig
            BitcoinScriptAddress corpRedeemAddress = corpMultiSig.GetScriptAddress(Network.RegTest);

            // Fund corp
            // 50 Coins come from first tx on chain - send corp 42 and change back to miner
            var         coin       = new Coin(context.SrcTxs[0].GetHash(), 0, context.SrcTxs[0].TotalOut, miner.ScriptPubKey);
            var         txBuilder  = new TransactionBuilder(Network.RegTest);
            Transaction fundP2shTx = txBuilder
                                     .AddCoins(new List <Coin> {
                coin
            })
                                     .AddKeys(miner)
                                     .Send(corpRedeemAddress, "42.00")
                                     .SendFees("0.001")
                                     .SetChange(miner.GetAddress())
                                     .BuildTransaction(true);

            Assert.True(txBuilder.Verify(fundP2shTx)); //check fully signed
            var state = new MempoolValidationState(false);

            Assert.True(await validator.AcceptToMemoryPool(state, fundP2shTx), $"Transaction: {nameof(fundP2shTx)} failed mempool validation.");

            // AliceBobNico corp. send 20 to Satoshi
            Coin[] corpCoins = fundP2shTx.Outputs
                               .Where(o => o.ScriptPubKey == corpRedeemAddress.ScriptPubKey)
                               .Select(o => ScriptCoin.Create(Network.RegTest, new OutPoint(fundP2shTx.GetHash(), fundP2shTx.Outputs.IndexOf(o)), o, corpMultiSig))
                               .ToArray();

            txBuilder = new TransactionBuilder(Network.RegTest);
            Transaction p2shSpendTx = txBuilder
                                      .AddCoins(corpCoins)
                                      .AddKeys(alice, bob)
                                      .Send(satoshi.GetAddress(), "20")
                                      .SendFees("0.001")
                                      .SetChange(corpRedeemAddress)
                                      .BuildTransaction(true);

            Assert.True(txBuilder.Verify(p2shSpendTx));

            Assert.True(await validator.AcceptToMemoryPool(state, p2shSpendTx), $"Transaction: {nameof(p2shSpendTx)} failed mempool validation.");
        }