public async Task ExtractNormalConversionDeposits_ReturnDeposits_AboveFasterThresholdAsync() { Block block = this.network.Consensus.ConsensusFactory.CreateBlock(); BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress(); byte[] opReturnBytes = Encoding.UTF8.GetBytes(targetAddress.ToString()); // Set amount to be less than the small threshold amount. CreateDepositTransaction(targetAddress, block, this.federationSettings.SmallDepositThresholdAmount - 1, opReturnBytes); byte[] ethOpReturnBytes = Encoding.UTF8.GetBytes(InterFluxOpReturnEncoder.Encode(DestinationChain.ETH, TargetETHAddress)); // Set amount to be exactly the small threshold amount. CreateConversionTransaction(block, DepositValidationHelper.ConversionTransactionMinimum - 1, ethOpReturnBytes); // Set amount to be greater than the small threshold amount. CreateConversionTransaction(block, DepositValidationHelper.ConversionTransactionMinimum + 1, ethOpReturnBytes); int blockHeight = 12345; IReadOnlyList <IDeposit> extractedDeposits = await this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight, this.retrievalTypeConfirmations); // Should only be 1, with the value just over the withdrawal fee. IEnumerable <IDeposit> applicable = extractedDeposits.Where(d => d.Amount > DepositValidationHelper.ConversionTransactionMinimum && d.RetrievalType == DepositRetrievalType.ConversionLarge); applicable.Count().Should().Be(1); foreach (IDeposit extractedDeposit in applicable) { Assert.True(extractedDeposit.Amount >= this.federationSettings.SmallDepositThresholdAmount); } }
public void DecodeDoesntThrowWhenFormatIsIncorrect() { Assert.False(InterFluxOpReturnEncoder.TryDecode("INTER_3_345345", out int _, out string _)); Assert.False(InterFluxOpReturnEncoder.TryDecode("INTER3_", out int _, out string _)); Assert.False(InterFluxOpReturnEncoder.TryDecode("INTERefsdvsdvdsvsdv", out int _, out string _)); Assert.False(InterFluxOpReturnEncoder.TryDecode("xvev456545cwsdfFSXVB365", out int _, out string _)); }
public void EncodeAndDecodeETHAddressLegacy_Pass() { bool result = InterFluxOpReturnEncoder.TryDecode("0xd2390da742872294BE05dc7359D7249d7C79460E", out int resultChain, out string resultAddress); Assert.True(result); Assert.Equal(DestinationChain.ETH, (DestinationChain)resultChain); Assert.Equal("0xd2390da742872294BE05dc7359D7249d7C79460E", resultAddress); }
public void EncodeAndDecodeETHAddress() { string address = "0xd2390da742872294BE05dc7359D7249d7C79460E"; string encoded = InterFluxOpReturnEncoder.Encode(DestinationChain.ETH, address); bool success = InterFluxOpReturnEncoder.TryDecode(encoded, out int resultChain, out string resultAddress); Assert.True(success); Assert.Equal(DestinationChain.ETH, (DestinationChain)resultChain); Assert.Equal(address, resultAddress); }
public MaturedBlocksProviderTests() { this.loggerFactory = Substitute.For <ILoggerFactory>(); this.logger = Substitute.For <ILogger>(); this.loggerFactory.CreateLogger(null).ReturnsForAnyArgs(this.logger); this.conversionRequestRepository = Substitute.For <IConversionRequestRepository>(); this.consensusManager = Substitute.For <IConsensusManager>(); this.network = new CirrusRegTest(); this.mainChainNetwork = new StraxRegTest(); this.opReturnDataReader = Substitute.For <IOpReturnDataReader>(); this.opReturnDataReader.TryGetTargetAddress(null, out string address).Returns(callInfo => { callInfo[1] = null; return(false); }); this.transactionBuilder = new TestTransactionBuilder(); this.addressHelper = new MultisigAddressHelper(this.network, this.mainChainNetwork); this.targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress(); this.opReturnBytes = Encoding.UTF8.GetBytes(InterFluxOpReturnEncoder.Encode(DestinationChain.STRAX, this.targetAddress.ToString())); this.federatedPegSettings = Substitute.For <IFederatedPegSettings>(); this.federatedPegSettings.MultiSigRedeemScript.Returns(this.addressHelper.PayToMultiSig); this.federatedPegSettings.MinimumConfirmationsSmallDeposits.Returns(5); this.federatedPegSettings.MinimumConfirmationsNormalDeposits.Returns(10); this.federatedPegSettings.MinimumConfirmationsLargeDeposits.Returns(20); this.federatedPegSettings.SmallDepositThresholdAmount.Returns(Money.Coins(10)); this.federatedPegSettings.NormalDepositThresholdAmount.Returns(Money.Coins(100)); this.consensusManager.GetBlocksAfterBlock(Arg.Any <ChainedHeader>(), MaturedBlocksProvider.MaturedBlocksBatchSize, Arg.Any <CancellationTokenSource>()).Returns(delegate(CallInfo info) { var chainedHeader = (ChainedHeader)info[0]; if (chainedHeader == null) { return(this.blocks.Where(x => x.ChainedHeader.Height <= this.consensusManager.Tip.Height).ToArray()); } return(this.blocks.SkipWhile(x => x.ChainedHeader.Height <= chainedHeader.Height).Where(x => x.ChainedHeader.Height <= this.consensusManager.Tip.Height).ToArray()); }); this.retrievalTypeConfirmations = new Dictionary <DepositRetrievalType, int> { [DepositRetrievalType.Small] = this.federatedPegSettings.MinimumConfirmationsSmallDeposits, [DepositRetrievalType.Normal] = this.federatedPegSettings.MinimumConfirmationsNormalDeposits, [DepositRetrievalType.Large] = this.federatedPegSettings.MinimumConfirmationsLargeDeposits, }; this.retrievalTypeConfirmations[DepositRetrievalType.Distribution] = this.federatedPegSettings.MinimumConfirmationsDistributionDeposits; this.retrievalTypeConfirmations[DepositRetrievalType.ConversionSmall] = this.federatedPegSettings.MinimumConfirmationsSmallDeposits; this.retrievalTypeConfirmations[DepositRetrievalType.ConversionNormal] = this.federatedPegSettings.MinimumConfirmationsNormalDeposits; this.retrievalTypeConfirmations[DepositRetrievalType.ConversionLarge] = this.federatedPegSettings.MinimumConfirmationsLargeDeposits; }
/// <inheritdoc /> public IDeposit ExtractDepositFromTransaction(Transaction transaction, int blockHeight, uint256 blockHash) { // Coinbase transactions can't have deposits. if (transaction.IsCoinBase) { return(null); } // Deposits have a certain structure. if (transaction.Outputs.Count != ExpectedNumberOfOutputsNoChange && transaction.Outputs.Count != ExpectedNumberOfOutputsChange) { return(null); } var depositsToMultisig = transaction.Outputs.Where(output => output.ScriptPubKey == this.depositScript && output.Value >= FederatedPegSettings.CrossChainTransferMinimum).ToList(); if (!depositsToMultisig.Any()) { return(null); } // Check the common case first. bool conversionTransaction = false; DestinationChain targetChain = DestinationChain.STRAX; if (!this.opReturnDataReader.TryGetTargetAddress(transaction, out string targetAddress)) { byte[] opReturnBytes = OpReturnDataReader.SelectBytesContentFromOpReturn(transaction).FirstOrDefault(); if (opReturnBytes != null && InterFluxOpReturnEncoder.TryDecode(opReturnBytes, out int destinationChain, out targetAddress)) { targetChain = (DestinationChain)destinationChain; } else { return(null); } conversionTransaction = true; }
public async Task ExtractConversionDeposits_BelowAndAboveThresholdAsync() { Block block = this.network.Consensus.ConsensusFactory.CreateBlock(); byte[] ethOpReturnBytes = Encoding.UTF8.GetBytes(InterFluxOpReturnEncoder.Encode(DestinationChain.ETH, TargetETHAddress)); CreateConversionTransaction(block, DepositValidationHelper.ConversionTransactionMinimum - 1, ethOpReturnBytes); CreateConversionTransaction(block, DepositValidationHelper.ConversionTransactionMinimum + 1, ethOpReturnBytes); int blockHeight = 12345; IReadOnlyList <IDeposit> extractedDeposits = await this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight, this.retrievalTypeConfirmations); // Should only be two, with the value just over the withdrawal fee. extractedDeposits.Count.Should().Be(1); foreach (IDeposit extractedDeposit in extractedDeposits) { Assert.True(extractedDeposit.Amount == DepositValidationHelper.ConversionTransactionMinimum + 1); } }
public void CanEncodeAndDecode() { int chain = 3; string address = "0x51EC92A3aB8cfcA412Ea43766A9259523fC81501"; string encoded = InterFluxOpReturnEncoder.Encode(chain, address); bool success = InterFluxOpReturnEncoder.TryDecode(encoded, out int resultChain, out string resultAddress); Assert.True(success); Assert.Equal(chain, resultChain); Assert.Equal(address, resultAddress); byte[] encodedBytes = Encoding.UTF8.GetBytes(encoded); bool success2 = InterFluxOpReturnEncoder.TryDecode(encodedBytes, out int resultChain2, out string resultAddress2); Assert.True(success2); Assert.Equal(chain, resultChain2); Assert.Equal(address, resultAddress2); }
public void ExtractLargeConversionDeposits_ReturnDeposits_AboveNormalThreshold() { Block block = this.network.Consensus.ConsensusFactory.CreateBlock(); // Create the target address. BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress(); byte[] opReturnBytes = Encoding.UTF8.GetBytes(targetAddress.ToString()); // Set amount to be less than deposit minimum CreateDepositTransaction(targetAddress, block, FederatedPegSettings.CrossChainTransferMinimum - 1, opReturnBytes); // Set amount to be less than the small threshold amount. CreateDepositTransaction(targetAddress, block, this.federationSettings.SmallDepositThresholdAmount - 1, opReturnBytes); // Set amount to be exactly the normal threshold amount. CreateDepositTransaction(targetAddress, block, this.federationSettings.NormalDepositThresholdAmount, opReturnBytes); byte[] ethOpReturnBytes = Encoding.UTF8.GetBytes(InterFluxOpReturnEncoder.Encode(DestinationChain.ETH, TargetETHAddress)); // Set amount to be equal to the normal threshold amount. CreateConversionTransaction(block, this.federationSettings.NormalDepositThresholdAmount, ethOpReturnBytes); // Set amount to be greater than the conversion deposit minimum amount. CreateConversionTransaction(block, Money.Coins(DepositExtractor.ConversionTransactionMinimum + 1), ethOpReturnBytes); int blockHeight = 12345; IReadOnlyList <IDeposit> extractedDeposits = this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight, new[] { DepositRetrievalType.ConversionLarge }); // Should only be 1, with the value just over the withdrawal fee. extractedDeposits.Count.Should().Be(1); foreach (IDeposit extractedDeposit in extractedDeposits) { Assert.True(extractedDeposit.Amount > this.federationSettings.NormalDepositThresholdAmount); Assert.Equal(TargetETHAddress, extractedDeposit.TargetAddress); } }
public void EncodeAndDecodeETHAddressLegacy_Fail() { bool result = InterFluxOpReturnEncoder.TryDecode("0xd2390da742872294BE05dc7359D7249d7C9460E", out int resultChain, out string resultAddress); Assert.False(result); }