/// <summary> /// Constructs and instance of memory pool behavior. /// Constructs a logger instance for memory pool behavior object. /// </summary> /// <param name="validator">Memory pool validator for validating transactions.</param> /// <param name="manager">Memory pool manager for managing the memory pool.</param> /// <param name="orphans">Memory pool orphans for managing orphan transactions.</param> /// <param name="connectionManager">Connection manager for managing peer connections.</param> /// <param name="initialBlockDownloadState">Provider of IBD state.</param> /// <param name="signals">Peer notifications available to subscribe to.</param> /// <param name="loggerFactory">Logger factory for creating logger.</param> public MempoolBehavior( IMempoolValidator validator, MempoolManager manager, MempoolOrphans orphans, IConnectionManager connectionManager, IInitialBlockDownloadState initialBlockDownloadState, Signals.Signals signals, ILoggerFactory loggerFactory) : this(validator, manager, orphans, connectionManager, initialBlockDownloadState, signals, loggerFactory.CreateLogger(typeof(MempoolBehavior).FullName)) { }
/// <summary> /// Constructs a wallet fee policy. /// </summary> /// <param name="blockPolicyEstimator">Block policy estimator.</param> /// <param name="mempoolValidator">Memory pool validator.</param> /// <param name="mempool">Memory pool.</param> /// <param name="network">Network node is running on.</param> /// <param name="nodeSettings">Settings for the the node.</param> public WalletFeePolicy(BlockPolicyEstimator blockPolicyEstimator, IMempoolValidator mempoolValidator, TxMempool mempool, Network network, NodeSettings nodeSettings) { this.blockPolicyEstimator = blockPolicyEstimator; this.mempoolValidator = mempoolValidator; this.mempool = mempool; this.minTxFee = nodeSettings.MinTxFeeRate; this.fallbackFee = nodeSettings.FallbackTxFeeRate; this.payTxFee = new FeeRate(0); this.maxTxFee = new Money(0.1M, MoneyUnit.BTC); this.minRelayTxFee = nodeSettings.MinRelayTxFeeRate; }
public BlocksDisconnectedSignaled( ITxMempool mempool, IMempoolValidator mempoolValidator, MempoolSchedulerLock mempoolLock, ILoggerFactory loggerFactory, ISignals signals) { this.mempool = mempool; this.mempoolValidator = mempoolValidator; this.mempoolLock = mempoolLock; this.signals = signals; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); }
public SignedMultisigTransactionBroadcasterTests() { this.loggerFactory = Substitute.For <ILoggerFactory>(); this.logger = Substitute.For <ILogger>(); this.federationGatewaySettings = Substitute.For <IFederationGatewaySettings>(); this.loggerFactory.CreateLogger(null).ReturnsForAnyArgs(this.logger); this.leaderReceiverSubscription = Substitute.For <IDisposable>(); this.store = Substitute.For <ICrossChainTransferStore>(); this.broadcasterManager = Substitute.For <IBroadcasterManager>(); this.asyncProvider = Substitute.For <IAsyncProvider>(); this.nodeLifetime = Substitute.For <INodeLifetime>(); this.ibdState = Substitute.For <IInitialBlockDownloadState>(); this.federationWalletManager = Substitute.For <IFederationWalletManager>(); this.federationWalletManager.IsFederationWalletActive().Returns(true); // Setup MempoolManager. this.dateTimeProvider = Substitute.For <IDateTimeProvider>(); this.nodeSettings = new NodeSettings(networksSelector: CirrusNetwork.NetworksSelector, protocolVersion: NBitcoin.Protocol.ProtocolVersion.ALT_PROTOCOL_VERSION); this.mempoolSettings = new MempoolSettings(this.nodeSettings) { MempoolExpiry = MempoolValidator.DefaultMempoolExpiry }; this.blockPolicyEstimator = new BlockPolicyEstimator( this.mempoolSettings, this.loggerFactory, this.nodeSettings); this.txMempool = new TxMempool( this.dateTimeProvider, this.blockPolicyEstimator, this.loggerFactory, this.nodeSettings); this.mempoolValidator = Substitute.For <IMempoolValidator>(); this.mempoolPersistence = Substitute.For <IMempoolPersistence>(); this.coinView = Substitute.For <ICoinView>(); this.mempoolManager = new MempoolManager( new MempoolSchedulerLock(), this.txMempool, this.mempoolValidator, this.dateTimeProvider, this.mempoolSettings, this.mempoolPersistence, this.coinView, this.loggerFactory, this.nodeSettings.Network); }
public async void AcceptToMemoryPool_TxAncestorsConflictSpend_ReturnsFalseAsync() { // TODO: Execute failure cases for CheckAncestors // - conflicting spend transaction string dataDir = GetTestDirectoryPath(this); var miner = new BitcoinSecret(new Key(), Network.RegTest); ITestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, miner.PubKey.Hash.ScriptPubKey, dataDir).ConfigureAwait(false); IMempoolValidator validator = context.MempoolValidator; var bob = new BitcoinSecret(new Key(), Network.RegTest); var txBuilder = new TransactionBuilder(Network.RegTest); //Create Coin from first tx on chain var coin = new Coin(context.SrcTxs[0].GetHash(), 0, context.SrcTxs[0].TotalOut, PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(miner.PubKey)); //Send 10 to Bob and return the rest as change to miner Transaction originalTx = txBuilder .AddCoins(coin) .AddKeys(miner) .Send(bob, "10.00") .SendFees("0.001") .SetChange(miner) .BuildTransaction(true); var state = new MempoolValidationState(false); //Mempool should accept it, there's nothing wrong Assert.True(await validator.AcceptToMemoryPool(state, originalTx).ConfigureAwait(false), $"Transaction: {nameof(originalTx)} failed mempool validation."); //Create second transaction spending the same coin Transaction conflictingTx = txBuilder .AddCoins(coin) .AddKeys(miner) .Send(bob, "10.00") .SendFees("0.001") .SetChange(miner) .BuildTransaction(true); //Mempool should reject the second transaction Assert.False(await validator.AcceptToMemoryPool(state, conflictingTx).ConfigureAwait(false), $"Transaction: {nameof(conflictingTx)} should have failed mempool validation."); Directory.Delete(dataDir, true); }
/// <summary> /// Constructs an instance of a memory pool manager object. /// </summary> /// <param name="mempoolLock">A lock for managing asynchronous access to memory pool.</param> /// <param name="memPool">Transaction memory pool for managing transactions in the memory pool.</param> /// <param name="validator">Memory pool validator for validating transactions.</param> /// <param name="orphans">Memory pool orphans for managing orphan transactions.</param> /// <param name="dateTimeProvider">Date and time information provider.</param> /// <param name="nodeArgs">Settings from the node.</param> /// <param name="mempoolPersistence">Memory pool persistence methods for loading and saving from storage.</param> /// <param name="loggerFactory">Logger factory for creating instance logger.</param> public MempoolManager( MempoolAsyncLock mempoolLock, TxMempool memPool, IMempoolValidator validator, MempoolOrphans orphans, IDateTimeProvider dateTimeProvider, NodeSettings nodeArgs, IMempoolPersistence mempoolPersistence, ILoggerFactory loggerFactory) { this.MempoolLock = mempoolLock; this.memPool = memPool; this.DateTimeProvider = dateTimeProvider; this.NodeArgs = nodeArgs; this.Orphans = orphans; this.Validator = validator; this.mempoolPersistence = mempoolPersistence; this.mempoolLogger = loggerFactory.CreateLogger(this.GetType().FullName); }
public async Task AcceptToMemoryPool_WithSegWitValidTxns_IsSuccessfullAsync() { string dataDir = Path.Combine("TestData", nameof(MempoolValidatorTest), nameof(this.AcceptToMemoryPool_WithSegWitValidTxns_IsSuccessfullAsync)); Directory.CreateDirectory(dataDir); BitcoinSecret miner = new BitcoinSecret(new Key(), Network.PurpleRegTest); ITestChainContext context = await TestChainFactory.CreateAsync(Network.PurpleRegTest, miner.PubKey.ScriptPubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey, dataDir); IMempoolValidator validator = context.MempoolValidator; Assert.NotNull(validator); BitcoinSecret bob = new BitcoinSecret(new Key(), Network.PurpleRegTest); // Fund Bob // 50 Coins come from first tx on chain - send bob 42 and change back to miner ScriptCoin witnessCoin = new ScriptCoin(context.SrcTxs[0].GetHash(), 0, context.SrcTxs[0].TotalOut, miner.PubKey.ScriptPubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey, miner.PubKey.ScriptPubKey); TransactionBuilder txBuilder = new TransactionBuilder(); Transaction p2shOverp2wpkh = txBuilder .AddCoins(witnessCoin) .AddKeys(miner) .Send(bob, "42.00") .SendFees("0.001") .SetChange(miner) .BuildTransaction(true); Assert.True(txBuilder.Verify(p2shOverp2wpkh)); //check fully signed // remove witness data from tx Transaction noWitTx = p2shOverp2wpkh.WithOptions(NetworkOptions.None); Assert.Equal(p2shOverp2wpkh.GetHash(), noWitTx.GetHash()); Assert.True(noWitTx.GetSerializedSize() < p2shOverp2wpkh.GetSerializedSize()); Assert.True(txBuilder.Verify(p2shOverp2wpkh)); //check fully signed MempoolValidationState state = new MempoolValidationState(false); Assert.True(await validator.AcceptToMemoryPool(state, p2shOverp2wpkh), $"Transaction: {nameof(p2shOverp2wpkh)} failed mempool validation."); Directory.Delete(dataDir, true); }
public async void AcceptToMemoryPool_WithValidP2PKHTxn_IsSuccessfull() { BitcoinSecret minerSecret = new BitcoinSecret(new Key(), Network.RegTest); ITestChainContext context = TestChainFactory.Create(Network.RegTest, minerSecret.PubKey.Hash.ScriptPubKey); IMempoolValidator validator = context.MempoolValidator; Assert.NotNull(validator); BitcoinSecret destSecret = new BitcoinSecret(new Key(), Network.RegTest); Transaction tx = new Transaction(); tx.AddInput(new TxIn(new OutPoint(context.SrcTxs[0].GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(minerSecret.PubKey))); tx.AddOutput(new TxOut(new Money(Money.CENT * 11), destSecret.PubKeyHash)); tx.Sign(minerSecret, false); MempoolValidationState state = new MempoolValidationState(false); bool isSuccess = await validator.AcceptToMemoryPool(state, tx); Assert.True(isSuccess, "P2PKH tx not valid."); }
/// <summary> /// Constructs an instance of memory pool behavior. /// </summary> /// <param name="validator">Memory pool validator for validating transactions.</param> /// <param name="manager">Memory pool manager for managing the memory pool.</param> /// <param name="orphans">Memory pool orphans for managing orphan transactions.</param> /// <param name="connectionManager">Connection manager for managing node connections.</param> /// <param name="chainState">Current block chain state.</param> /// <param name="signals">Node notifications available to subscribe to.</param> /// <param name="logger">Instance logger for memory pool behavior.</param> public MempoolBehavior( IMempoolValidator validator, MempoolManager manager, MempoolOrphans orphans, IConnectionManager connectionManager, ChainState chainState, Signals.Signals signals, ILogger logger) { this.validator = validator; this.manager = manager; this.orphans = orphans; this.connectionManager = connectionManager; this.chainState = chainState; this.signals = signals; this.logger = logger; this.inventoryTxToSend = new Dictionary <uint256, uint256>(); this.filterInventoryKnown = new Dictionary <uint256, uint256>(); }
/// <summary> /// Constructs an instance of a memory pool manager object. /// </summary> /// <param name="mempoolLock">A lock for managing asynchronous access to memory pool.</param> /// <param name="memPool">Transaction memory pool for managing transactions in the memory pool.</param> /// <param name="validator">Memory pool validator for validating transactions.</param> /// <param name="orphans">Memory pool orphans for managing orphan transactions.</param> /// <param name="dateTimeProvider">Date and time information provider.</param> /// <param name="nodeArgs">Settings from the node.</param> /// <param name="mempoolSettings">Settings for memory pool.</param> /// <param name="mempoolPersistence">Memory pool persistence methods for loading and saving from storage.</param> /// <param name="loggerFactory">Logger factory for creating instance logger.</param> public MempoolManager( MempoolSchedulerLock mempoolLock, TxMempool memPool, IMempoolValidator validator, MempoolOrphans orphans, IDateTimeProvider dateTimeProvider, MempoolSettings mempoolSettings, IMempoolPersistence mempoolPersistence, CoinView coinView, ILoggerFactory loggerFactory) { this.MempoolLock = mempoolLock; this.memPool = memPool; this.DateTimeProvider = dateTimeProvider; this.mempoolSettings = mempoolSettings; this.Orphans = orphans; this.Validator = validator; this.mempoolPersistence = mempoolPersistence; this.coinView = coinView; this.mempoolLogger = loggerFactory.CreateLogger(this.GetType().FullName); }
/// <summary> /// Constructs an instance of a MempoolSignaled object. /// Starts the block notification loop to memory pool behaviors for connected nodes. /// </summary> /// <param name="manager">Memory pool manager injected dependency.</param> /// <param name="chain">Concurrent chain injected dependency.</param> /// <param name="connection">Connection manager injected dependency.</param> /// <param name="nodeLifetime">Node lifetime injected dependency.</param> /// <param name="asyncLoopFactory">Asynchronous loop factory injected dependency.</param> /// <param name="mempoolLock">The mempool lock.</param> /// <param name="memPool">the mempool.</param> /// <param name="validator">The mempool validator.</param> /// <param name="mempoolOrphans">The mempool orphan list.</param> public MempoolSignaled( MempoolManager manager, ConcurrentChain chain, IConnectionManager connection, INodeLifetime nodeLifetime, IAsyncLoopFactory asyncLoopFactory, MempoolSchedulerLock mempoolLock, ITxMempool memPool, IMempoolValidator validator, MempoolOrphans mempoolOrphans) { this.manager = manager; this.chain = chain; this.connection = connection; this.nodeLifetime = nodeLifetime; this.asyncLoopFactory = asyncLoopFactory; this.mempoolLock = mempoolLock; this.memPool = memPool; this.validator = validator; this.mempoolOrphans = mempoolOrphans; }
public MempoolManager( MempoolSchedulerLock mempoolLock, ITxMempool memPool, IMempoolValidator validator, IDateTimeProvider dateTimeProvider, MempoolSettings mempoolSettings, IMempoolPersistence mempoolPersistence, ICoinView coinView, ILoggerFactory loggerFactory, Network network) { this.MempoolLock = mempoolLock; this.memPool = memPool; this.DateTimeProvider = dateTimeProvider; this.mempoolSettings = mempoolSettings; this.Validator = validator; this.mempoolPersistence = mempoolPersistence; this.coinView = coinView; this.network = network; this.logger = loggerFactory.CreateLogger(GetType().FullName); }
/// <summary> /// Constructs an instance of memory pool behavior. /// </summary> /// <param name="validator">Memory pool validator for validating transactions.</param> /// <param name="manager">Memory pool manager for managing the memory pool.</param> /// <param name="orphans">Memory pool orphans for managing orphan transactions.</param> /// <param name="connectionManager">Connection manager for managing peer connections.</param> /// <param name="initialBlockDownloadState">Provider of IBD state.</param> /// <param name="signals">Peer notifications available to subscribe to.</param> /// <param name="logger">Instance logger for memory pool behavior.</param> /// <param name="network">The blockchain network.</param> public MempoolBehavior( IMempoolValidator validator, MempoolManager manager, MempoolOrphans orphans, IConnectionManager connectionManager, IInitialBlockDownloadState initialBlockDownloadState, Signals.Signals signals, ILogger logger, Network network) { this.validator = validator; this.manager = manager; this.orphans = orphans; this.connectionManager = connectionManager; this.initialBlockDownloadState = initialBlockDownloadState; this.signals = signals; this.logger = logger; this.network = network; this.inventoryTxToSend = new Dictionary <uint256, uint256>(); this.filterInventoryKnown = new Dictionary <uint256, uint256>(); }
public WalletManager( ILoggerFactory loggerFactory, IConnectionManager connectionManager, Network network, ConcurrentChain chain, NodeSettings settings, DataFolder dataFolder, IWalletFeePolicy walletFeePolicy, IAsyncLoopFactory asyncLoopFactory, INodeLifetime nodeLifetime, IMempoolValidator mempoolValidator = null) // mempool does not exist in a light wallet { Guard.NotNull(loggerFactory, nameof(loggerFactory)); Guard.NotNull(network, nameof(network)); Guard.NotNull(chain, nameof(chain)); Guard.NotNull(settings, nameof(settings)); Guard.NotNull(dataFolder, nameof(dataFolder)); Guard.NotNull(walletFeePolicy, nameof(walletFeePolicy)); Guard.NotNull(asyncLoopFactory, nameof(asyncLoopFactory)); Guard.NotNull(nodeLifetime, nameof(nodeLifetime)); this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.Wallets = new ConcurrentBag <Wallet>(); this.connectionManager = connectionManager; this.network = network; this.coinType = (CoinType)network.Consensus.CoinType; this.chain = chain; this.settings = settings; this.dataFolder = dataFolder; this.walletFeePolicy = walletFeePolicy; this.mempoolValidator = mempoolValidator; this.asyncLoopFactory = asyncLoopFactory; this.nodeLifetime = nodeLifetime; // register events this.TransactionFound += this.OnTransactionFound; }
public async Task AcceptToMemoryPool_WithValidP2PKHTxn_IsSuccessfullAsync() { string dataDir = GetTestDirectoryPath(this); var minerSecret = new BitcoinSecret(new Key(), KnownNetworks.RegTest); ITestChainContext context = await TestChainFactory.CreateAsync(KnownNetworks.RegTest, minerSecret.PubKey.Hash.ScriptPubKey, dataDir); IMempoolValidator validator = context.MempoolValidator; Assert.NotNull(validator); var destSecret = new BitcoinSecret(new Key(), KnownNetworks.RegTest); var tx = new Transaction(); tx.AddInput(new TxIn(new OutPoint(context.SrcTxs[0].GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(minerSecret.PubKey))); tx.AddOutput(new TxOut(new Money(Money.CENT * 11), destSecret.PubKeyHash)); tx.Sign(KnownNetworks.RegTest, minerSecret, false); var state = new MempoolValidationState(false); bool isSuccess = await validator.AcceptToMemoryPool(state, tx); Assert.True(isSuccess, "P2PKH tx not valid."); }
/// <summary> /// Constructs an instance of a MempoolSignaled object. /// Starts the block notification loop to memory pool behaviors for connected nodes. /// </summary> /// <param name="manager">Memory pool manager injected dependency.</param> /// <param name="chainIndexer">Concurrent chain injected dependency.</param> /// <param name="connection">Connection manager injected dependency.</param> /// <param name="nodeLifetime">Node lifetime injected dependency.</param> /// <param name="asyncProvider">Asynchronous loop factory injected dependency.</param> /// <param name="mempoolLock">The mempool lock.</param> /// <param name="memPool">the mempool.</param> /// <param name="validator">The mempool validator.</param> /// <param name="mempoolOrphans">The mempool orphan list.</param> public MempoolSignaled( MempoolManager manager, ChainIndexer chainIndexer, IConnectionManager connection, INodeLifetime nodeLifetime, IAsyncProvider asyncProvider, MempoolSchedulerLock mempoolLock, ITxMempool memPool, IMempoolValidator validator, MempoolOrphans mempoolOrphans, ISignals signals) { this.manager = manager; this.chainIndexer = chainIndexer; this.connection = connection; this.nodeLifetime = nodeLifetime; this.asyncProvider = asyncProvider; this.mempoolLock = mempoolLock; this.memPool = memPool; this.validator = validator; this.mempoolOrphans = mempoolOrphans; this.signals = signals; }
public MempoolBehavior( IMempoolValidator validator, MempoolManager mempoolManager, MempoolOrphans orphans, IConnectionManager connectionManager, IInitialBlockDownloadState initialBlockDownloadState, Signals.Signals signals, ILoggerFactory loggerFactory, Network network) { this.validator = validator; this.mempoolManager = mempoolManager; this.orphans = orphans; this.connectionManager = connectionManager; this.initialBlockDownloadState = initialBlockDownloadState; this.signals = signals; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.loggerFactory = loggerFactory; this.network = network; this.lockObject = new object(); this.inventoryTxToSend = new HashSet <uint256>(); this.filterInventoryKnown = new HashSet <uint256>(); }
public WalletFeePolicy(BlockPolicyEstimator blockPolicyEstimator, IMempoolValidator mempoolValidator, TxMempool mempool, Network network) { this.blockPolicyEstimator = blockPolicyEstimator; this.mempoolValidator = mempoolValidator; this.mempool = mempool; this.minTxFee = new FeeRate(1000); this.fallbackFee = new FeeRate(20000); this.payTxFee = new FeeRate(0); this.maxTxFee = new Money(0.1M, MoneyUnit.BTC); this.minRelayTxFee = MempoolValidator.MinRelayTxFee; // this is a very very ugly hack // the fee constants should be set at the // network level or the consensus options if (network.Name.ToLower().Contains("stratis")) { this.minTxFee = new FeeRate(10000); this.fallbackFee = new FeeRate(40000); this.payTxFee = new FeeRate(0); this.maxTxFee = new Money(0.1M, MoneyUnit.BTC); this.minRelayTxFee = new FeeRate(10000); } }
public FullNodeBroadcasterManager(IConnectionManager connectionManager, IMempoolValidator mempoolValidator) : base(connectionManager) { Guard.NotNull(mempoolValidator, nameof(mempoolValidator)); this.mempoolValidator = mempoolValidator; }
/// <summary> /// Constructs a memory pool coin view. /// </summary> /// <param name="inner">The backing coin view.</param> /// <param name="memPool">Transaction memory pool for managing transactions in the memory pool.</param> /// <param name="mempoolLock">A lock for managing asynchronous access to memory pool.</param> /// <param name="mempoolValidator">Memory pool validator for validating transactions.</param> public MempoolCoinView(CoinView inner, ITxMempool memPool, SchedulerLock mempoolLock, IMempoolValidator mempoolValidator) { this.Inner = inner; this.memPool = memPool; this.mempoolLock = mempoolLock; this.mempoolValidator = mempoolValidator; this.Set = new UnspentOutputSet(); }
public async Task AcceptToMemoryPool_WithP2SHValidTxns_IsSuccessfullAsync() { string dataDir = Path.Combine("TestData", nameof(MempoolValidatorTest), nameof(this.AcceptToMemoryPool_WithP2SHValidTxns_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 }); // P2SH address for corp multi-sig BitcoinScriptAddress corpRedeemAddress = corpMultiSig.GetScriptAddress(Network.PurpleRegTest); // 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 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 MempoolValidationState 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 => new ScriptCoin(new OutPoint(fundP2shTx.GetHash(), fundP2shTx.Outputs.IndexOf(o)), o, corpMultiSig)) .ToArray(); txBuilder = new TransactionBuilder(); 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."); Directory.Delete(dataDir, true); }
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); }
public MempoolBroadcastCheck(IMempoolValidator mempoolValidator) { Guard.NotNull(mempoolValidator, nameof(mempoolValidator)); this.mempoolValidator = mempoolValidator; }
public FullNodeBroadcasterManager(IConnectionManager connectionManager, IMempoolValidator mempoolValidator) : base() { this.connectionManager = connectionManager ?? throw new ArgumentNullException(nameof(connectionManager)); this.mempoolValidator = mempoolValidator ?? throw new ArgumentNullException(nameof(mempoolValidator)); }
public async Task AcceptToMemoryPool_WithMultiSigValidTxns_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 }); // 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 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 var 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(Network.RegTest); 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(Network.RegTest); 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."); }