示例#1
0
        private Transaction[] SetupDummyInputs(TxOutRepository coinsRet)
        {
            Transaction[] dummyTransactions = Enumerable.Range(0, 2).Select(_ => new Transaction()).ToArray();

            // Add some keys to the keystore:
            Key[] key = Enumerable.Range(0, 4).Select((_, i) => new Key(i % 2 != 0)).ToArray();


            // Create some dummy input transactions
            dummyTransactions[0].Outputs.AddRange(Enumerable.Range(0, 2).Select(_ => new TxOut()));
            dummyTransactions[0].Outputs[0].Value        = 11 * Money.CENT;
            dummyTransactions[0].Outputs[0].ScriptPubKey = dummyTransactions[0].Outputs[0].ScriptPubKey + key[0].PubKey.ToBytes() + OpcodeType.OP_CHECKSIG;
            dummyTransactions[0].Outputs[1].Value        = 50 * Money.CENT;
            dummyTransactions[0].Outputs[1].ScriptPubKey = dummyTransactions[0].Outputs[1].ScriptPubKey + key[1].PubKey.ToBytes() + OpcodeType.OP_CHECKSIG;
            coinsRet.AddFromTransaction(dummyTransactions[0]);


            dummyTransactions[1].Outputs.AddRange(Enumerable.Range(0, 2).Select(_ => new TxOut()));
            dummyTransactions[1].Outputs[0].Value        = 21 * Money.CENT;
            dummyTransactions[1].Outputs[0].ScriptPubKey = StandardScripts.PayToAddress(key[2].PubKey.GetAddress(Network.Main));
            dummyTransactions[1].Outputs[1].Value        = 22 * Money.CENT;
            dummyTransactions[1].Outputs[1].ScriptPubKey = StandardScripts.PayToAddress(key[3].PubKey.GetAddress(Network.Main));
            coinsRet.AddFromTransaction(dummyTransactions[1]);


            return(dummyTransactions);
        }
示例#2
0
        public void test_Get()
        {
            //CBasicKeyStore keystore;
            //CCoinsView coinsDummy;
            TxOutRepository coins = new TxOutRepository();             //(coinsDummy);

            Transaction[] dummyTransactions = SetupDummyInputs(coins); //(keystore, coins);

            Transaction t1 = new Transaction();

            t1.Inputs.AddRange(Enumerable.Range(0, 3).Select(_ => new TxIn()));
            t1.Inputs[0].PrevOut.Hash = dummyTransactions[0].GetHash();
            t1.Inputs[0].PrevOut.N    = 1;
            t1.Inputs[0].ScriptSig   += new byte[65];
            t1.Inputs[1].PrevOut.Hash = dummyTransactions[1].GetHash();
            t1.Inputs[1].PrevOut.N    = 0;
            t1.Inputs[1].ScriptSig    = t1.Inputs[1].ScriptSig + new byte[65] + Enumerable.Range(0, 33).Select(_ => (byte)4);
            t1.Inputs[2].PrevOut.Hash = dummyTransactions[1].GetHash();
            t1.Inputs[2].PrevOut.N    = 1;
            t1.Inputs[2].ScriptSig    = t1.Inputs[2].ScriptSig + new byte[65] + Enumerable.Range(0, 33).Select(_ => (byte)4);
            t1.Outputs.AddRange(Enumerable.Range(0, 2).Select(_ => new TxOut()));
            t1.Outputs[0].Value         = 90 * Money.CENT;
            t1.Outputs[0].ScriptPubKey += OpcodeType.OP_1;

            Assert.True(StandardScripts.AreInputsStandard(t1, coins));
            //Assert.Equal(coins.GetValueIn(t1), (50+21+22)*Money.CENT);

            //// Adding extra junk to the scriptSig should make it non-standard:
            t1.Inputs[0].ScriptSig += OpcodeType.OP_11;
            Assert.True(!StandardScripts.AreInputsStandard(t1, coins));

            //// ... as should not having enough:
            t1.Inputs[0].ScriptSig = new Script();
            Assert.True(!StandardScripts.AreInputsStandard(t1, coins));
        }
        public async Task FirstTestnetTransactionTest()
        {
            var previousId = "b7773b4204686925e0cf607fb03250f0a18ce35cda48ac3ca8c004c33a9c3841";
            var targetHash = Address.FromPayToPublicKeyHashAddress("mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv", true);
            var changeHash = Address.FromPayToPublicKeyHashAddress("mvzHKaHbDMaLdNbDrPuiSbGV91o6ADjCAK", true);
            var transacion = new Transaction(1, false,
                                             new [] { new TransactionInput(Cipher.ToBytes(previousId), 1, new Script(), new Script(), 0) },
                                             new []
            {
                new TransactionOutput(600000, StandardScripts.PayToPubKeyHash(targetHash)),
                new TransactionOutput(395000, StandardScripts.PayToPubKeyHash(changeHash)),
            },
                                             0, true);

            var privateKey = new PrivateKey(Cipher.Hash256(Encoding.ASCII.GetBytes("Tim's testnet address")).ToBigInteger());
            var wallet     = new Wallet(new [] { privateKey });

            var signedTransaction = await IntegrationSetup.Testnet.Signer.SignTransaction(wallet, transacion, SigHashType.All);

            Assert.NotNull(signedTransaction.ToHex());

            // Broadcaster is not an API
            // var handler = new HttpClientHandler {CookieContainer = new CookieContainer()};
            // var broadcaster = new TransactionBroadcaster(new HttpClient(handler)
            //     {BaseAddress = new Uri("https://live.blockcypher.com/btc-testnet/pushtx")});
            // await broadcaster.Broadcast(signedTranaction);
        }
        // Check for standard transaction types
        // @param[in] mapInputs    Map of previous transactions that have outputs we're spending
        // @return True if all inputs (scriptSigs) use only standard transaction forms
        private bool AreInputsStandard(Transaction tx, MempoolCoinView mapInputs)
        {
            if (tx.IsCoinBase)
            {
                return(true);                // Coinbases don't use vin normally
            }
            foreach (TxIn txin in tx.Inputs)
            {
                var prev     = mapInputs.GetOutputFor(txin);
                var template = StandardScripts.GetTemplateFromScriptPubKey(prev.ScriptPubKey);
                if (template == null)
                {
                    return(false);
                }

                if (template.Type == TxOutType.TX_SCRIPTHASH)
                {
                    if (prev.ScriptPubKey.GetSigOpCount(true) > 15)                     //MAX_P2SH_SIGOPS
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#5
0
        /// <inheritdoc cref="IScriptAddressReader.GetAddressFromScriptPubKey"/>
        public string GetAddressFromScriptPubKey(Network network, Script script)
        {
            var scriptTemplate = StandardScripts.GetTemplateFromScriptPubKey(script);

            var destinationAddress = string.Empty;

            switch (scriptTemplate.Type)
            {
            // Pay to PubKey can be found in outputs of staking transactions.
            case TxOutType.TX_PUBKEY:
                PubKey pubKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(script);
                destinationAddress = pubKey.GetAddress(network).ToString();
                break;

            // Pay to PubKey hash is the regular, most common type of output.
            case TxOutType.TX_PUBKEYHASH:
                destinationAddress = script.GetDestinationAddress(network).ToString();
                break;

            case TxOutType.TX_NONSTANDARD:
            case TxOutType.TX_SCRIPTHASH:
            case TxOutType.TX_MULTISIG:
            case TxOutType.TX_NULL_DATA:
            case TxOutType.TX_SEGWIT:
                break;
            }

            return(destinationAddress);
        }
        public static string[] GetAddress(Script script)
        {
            var template = StandardScripts.GetTemplateFromScriptPubKey(script);

            switch (template?.Type)
            {
            case TxOutType.TX_PUBKEY:
            case TxOutType.TX_MULTISIG:
                var pubkeys = script.GetDestinationPublicKeys(_network);
                return(pubkeys.Select(p => p.GetAddress(_network).ToString()).ToArray());

            case TxOutType.TX_PUBKEYHASH:
            case TxOutType.TX_SCRIPTHASH:
            case TxOutType.TX_SEGWIT:
                var bitcoinAddress = script.GetDestinationAddress(_network);
                return(bitcoinAddress != null ? new[] { bitcoinAddress.ToString() } : new string[0]);

            case TxOutType.TX_COLDSTAKE:
                if (ColdStakingScriptTemplate.Instance.ExtractScriptPubKeyParameters(script, out _, out var coldPubKeyHash))
                {
                    return(new[]
                    {
                        coldPubKeyHash.GetAddress(_network).ToString()
                    });
                }

                return(new string[0]);

            default:
                return(new string[0]);
            }
        }
示例#7
0
        public void test_IsStandard()
        {
            var coins = new TxOutRepository();

            Transaction[] dummyTransactions = SetupDummyInputs(coins);

            Transaction t = new Transaction();

            t.Inputs.Add(new TxIn());
            t.Inputs[0].PrevOut.Hash = dummyTransactions[0].GetHash();
            t.Inputs[0].PrevOut.N    = 1;
            t.Inputs[0].ScriptSig    = new Script(Op.GetPushOp(new byte[65]));
            t.Outputs.Add(new TxOut());
            t.Outputs[0].Value = 90 * Money.CENT;
            Key key       = new Key(true);
            var payToHash = new PayToPubkeyHashTemplate();

            t.Outputs[0].ScriptPubKey = payToHash.GenerateScriptPubKey(key.PubKey.ID);

            Assert.True(StandardScripts.IsStandardTransaction(t));

            t.Outputs[0].Value = 501;             //dust
            Assert.True(!StandardScripts.IsStandardTransaction(t));

            t.Outputs[0].Value = 601;             // not dust
            Assert.True(StandardScripts.IsStandardTransaction(t));

            t.Outputs[0].ScriptPubKey = new Script() + OpcodeType.OP_1;
            Assert.True(!StandardScripts.IsStandardTransaction(t));

            // 40-byte TX_NULL_DATA (standard)
            t.Outputs[0].ScriptPubKey = new Script() + OpcodeType.OP_RETURN + ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
            Assert.True(StandardScripts.IsStandardTransaction(t));

            // 41-byte TX_NULL_DATA (non-standard)
            t.Outputs[0].ScriptPubKey = new Script() + OpcodeType.OP_RETURN + ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
            Assert.True(!StandardScripts.IsStandardTransaction(t));

            // TX_NULL_DATA w/o PUSHDATA
            t.Outputs.Clear();
            t.Outputs.Add(new TxOut());
            t.Outputs[0].ScriptPubKey = new Script() + OpcodeType.OP_RETURN;
            Assert.True(StandardScripts.IsStandardTransaction(t));

            // Only one TX_NULL_DATA permitted in all cases
            t.Outputs.Add(new TxOut());
            t.Outputs.Add(new TxOut());
            t.Outputs[0].ScriptPubKey = new Script() + OpcodeType.OP_RETURN + ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
            t.Outputs[1].ScriptPubKey = new Script() + OpcodeType.OP_RETURN + ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
            Assert.True(!StandardScripts.IsStandardTransaction(t));

            t.Outputs[0].ScriptPubKey = new Script() + OpcodeType.OP_RETURN + ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
            t.Outputs[1].ScriptPubKey = new Script() + OpcodeType.OP_RETURN;
            Assert.True(!StandardScripts.IsStandardTransaction(t));

            t.Outputs[0].ScriptPubKey = new Script() + OpcodeType.OP_RETURN;
            t.Outputs[1].ScriptPubKey = new Script() + OpcodeType.OP_RETURN;
            Assert.True(!StandardScripts.IsStandardTransaction(t));
        }
示例#8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SyncOperations"/> class.
        /// </summary>
        public SyncOperations(IStorage storage, ILogger <SyncOperations> logger, IOptions <NakoConfiguration> configuration)
        {
            this.configuration = configuration.Value;
            this.log           = logger;
            this.storage       = storage;

            // Register the cold staking template.
            StandardScripts.RegisterStandardScriptTemplate(ColdStakingScriptTemplate.Instance);
        }
示例#9
0
        private static Script CombineSignatures(Script scriptPubKey, TransactionChecker checker, byte[][] sigs1,
                                                byte[][] sigs2)
        {
            var template = StandardScripts.GetTemplateFromScriptPubKey(scriptPubKey);

            if (template is PayToPubkeyHashTemplate)
            {
                scriptPubKey = new KeyId(scriptPubKey.ToBytes(true).SafeSubArray(1, 20)).ScriptPubKey;
                template     = StandardScripts.GetTemplateFromScriptPubKey(scriptPubKey);
            }

            if (template == null || template is TxNullDataTemplate)
            {
                return(PushAll(Max(sigs1, sigs2)));
            }

            if (template is PayToPubkeyTemplate || template is PayToPubkeyHashTemplate)
            {
                if (sigs1.Length == 0 || sigs1[0].Length == 0)
                {
                    return(PushAll(sigs2));
                }

                return(PushAll(sigs1));
            }

            if (template is PayToScriptHashTemplate)
            {
                if (sigs1.Length == 0 || sigs1[sigs1.Length - 1].Length == 0)
                {
                    return(PushAll(sigs2));
                }

                if (sigs2.Length == 0 || sigs2[sigs2.Length - 1].Length == 0)
                {
                    return(PushAll(sigs1));
                }

                var redeemBytes = sigs1[sigs1.Length - 1];
                var redeem      = new Script(redeemBytes);
                sigs1 = sigs1.Take(sigs1.Length - 1).ToArray();
                sigs2 = sigs2.Take(sigs2.Length - 1).ToArray();
                var result = CombineSignatures(redeem, checker, sigs1, sigs2);
                result += Op.GetPushOp(redeemBytes);
                return(result);
            }

            if (template is PayToMultiSigTemplate)
            {
                return(CombineMultisig(scriptPubKey, checker, sigs1, sigs2));
            }

            return(null);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SyncOperations"/> class.
        /// </summary>
        public SyncOperations(IStorage storage, ILogger <SyncOperations> logger, IOptions <IndexerSettings> configuration, IMemoryCache cache)
        {
            this.configuration = configuration.Value;
            log          = logger;
            this.storage = storage;
            this.cache   = cache;

            // Register the cold staking template.
            StandardScripts.RegisterStandardScriptTemplate(ColdStakingScriptTemplate.Instance);

            watch        = Stopwatch.Start();
            cacheOptions = new MemoryCacheEntryOptions().SetAbsoluteExpiration(CacheKeys.BlockCountTime);
        }
        protected override void CheckPubKey(Transaction transaction, List <TransactionPolicyError> errors)
        {
            if (this.CheckScriptPubKey)
            {
                foreach (Coin txout in transaction.Outputs.AsCoins())
                {
                    ScriptTemplate template = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey);

                    if (template == null && !txout.ScriptPubKey.IsSmartContractExec())
                    {
                        errors.Add(new OutputPolicyError("Non-Standard scriptPubKey", (int)txout.Outpoint.N));
                    }
                }
            }
        }
示例#12
0
        public static IFullNodeBuilder UseColdStakingWallet(this IFullNodeBuilder fullNodeBuilder)
        {
            // Ensure that this feature is only used on a Stratis network.
            if (!fullNodeBuilder.Network.Consensus.IsProofOfStake)
            {
                throw new InvalidOperationException("Cold staking can only be used on a Stratis network.");
            }

            // Register the cold staking script template.
            StandardScripts.RegisterStandardScriptTemplate(ColdStakingScriptTemplate.Instance);

            LoggingConfiguration.RegisterFeatureNamespace <ColdStakingFeature>("wallet");

            fullNodeBuilder.ConfigureFeature(features =>
            {
                features
                .AddFeature <ColdStakingFeature>()
                .DependOn <MempoolFeature>()
                .DependOn <BlockStoreFeature>()
                .DependOn <RPCFeature>()
                .FeatureServices(services =>
                {
                    services.AddSingleton <IWalletSyncManager, WalletSyncManager>();
                    services.AddSingleton <IWalletTransactionHandler, WalletTransactionHandler>();
                    services.AddSingleton <IWalletManager, ColdStakingManager>();
                    services.AddSingleton <IWalletFeePolicy, WalletFeePolicy>();
                    services.AddSingleton <ColdStakingController>();
                    services.AddSingleton <WalletController>();
                    services.AddSingleton <WalletRPCController>();
                    services.AddSingleton <IBroadcasterManager, FullNodeBroadcasterManager>();
                    services.AddSingleton <BroadcasterBehavior>();
                    services.AddSingleton <WalletSettings>();
                    services.AddSingleton <IScriptAddressReader>(new ScriptAddressReader());
                    services.AddSingleton <StandardTransactionPolicy>();
                    services.AddSingleton <IAddressBookManager, AddressBookManager>();
                });
            });

            return(fullNodeBuilder);
        }
示例#13
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SyncOperations"/> class.
        /// </summary>
        public SyncOperations(
            IStorage storage,
            ILogger <SyncOperations> logger,
            IOptions <IndexerSettings> configuration,
            IMemoryCache cache,
            GlobalState globalState, ICryptoClientFactory clientFactory,
            ISyncBlockTransactionOperationBuilder blockInfoEnrichment, IMongoDb db)
        {
            this.configuration = configuration.Value;
            log                         = logger;
            this.storage                = storage;
            this.cache                  = cache;
            this.globalState            = globalState;
            this.clientFactory          = clientFactory;
            transactionOperationBuilder = blockInfoEnrichment;
            this.db                     = db;

            // Register the cold staking template.
            StandardScripts.RegisterStandardScriptTemplate(ColdStakingScriptTemplate.Instance);

            cacheOptions = new MemoryCacheEntryOptions().SetAbsoluteExpiration(CacheKeys.BlockCountTime);
        }
        public TransactionPolicyError[] Check(Transaction transaction, ICoin[] spentCoins)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException("transaction");
            }

            spentCoins = spentCoins ?? new ICoin[0];

            List <TransactionPolicyError> errors = new List <TransactionPolicyError>();



            foreach (var input in transaction.Inputs.AsIndexedInputs())
            {
                var coin = spentCoins.FirstOrDefault(s => s.Outpoint == input.PrevOut);
                if (coin != null)
                {
                    if (ScriptVerify != null)
                    {
                        ScriptError error;
                        if (!VerifyScript(input, coin.TxOut.ScriptPubKey, coin.TxOut.Value, ScriptVerify.Value, out error))
                        {
                            errors.Add(new ScriptPolicyError(input, error, ScriptVerify.Value, coin.TxOut.ScriptPubKey));
                        }
                    }
                }

                var txin = input.TxIn;
                if (txin.ScriptSig.Length > MaxScriptSigLength)
                {
                    errors.Add(new InputPolicyError("Max scriptSig length exceeded actual is " + txin.ScriptSig.Length + ", max is " + MaxScriptSigLength, input));
                }
                if (!txin.ScriptSig.IsPushOnly)
                {
                    errors.Add(new InputPolicyError("All operation should be push", input));
                }
                if (!txin.ScriptSig.HasCanonicalPushes)
                {
                    errors.Add(new InputPolicyError("All operation should be canonical push", input));
                }
            }

            if (CheckScriptPubKey)
            {
                foreach (var txout in transaction.Outputs.AsCoins())
                {
                    var template = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey);
                    if (template == null)
                    {
                        errors.Add(new OutputPolicyError("Non-Standard scriptPubKey", (int)txout.Outpoint.N));
                    }
                }
            }

            int txSize = transaction.GetSerializedSize();

            if (MaxTransactionSize != null)
            {
                if (txSize >= MaxTransactionSize.Value)
                {
                    errors.Add(new TransactionSizePolicyError(txSize, MaxTransactionSize.Value));
                }
            }

            var fees = transaction.GetFee(spentCoins);

            if (fees != null)
            {
                if (CheckFee)
                {
                    if (MaxTxFee != null)
                    {
                        var max = MaxTxFee.GetFee(txSize);
                        if (fees > max)
                        {
                            errors.Add(new FeeTooHighPolicyError(fees, max));
                        }
                    }

                    if (MinRelayTxFee != null)
                    {
                        if (MinRelayTxFee != null)
                        {
                            var min = MinRelayTxFee.GetFee(txSize);
                            if (fees < min)
                            {
                                errors.Add(new FeeTooLowPolicyError(fees, min));
                            }
                        }
                    }
                }
            }
            if (MinRelayTxFee != null)
            {
                foreach (var output in transaction.Outputs)
                {
                    var bytes = output.ScriptPubKey.ToBytes(true);
                    if (output.IsDust(MinRelayTxFee) && !IsOpReturn(bytes))
                    {
                        errors.Add(new DustPolicyError(output.Value, output.GetDustThreshold(MinRelayTxFee)));
                    }
                }
            }
            var opReturnCount = transaction.Outputs.Select(o => o.ScriptPubKey.ToBytes(true)).Count(b => IsOpReturn(b));

            if (opReturnCount > 1)
            {
                errors.Add(new TransactionPolicyError("More than one op return detected"));
            }
            return(errors.ToArray());
        }
 public virtual bool IsStandardOutput(TxOut txout)
 {
     return(StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey) != null);
 }
示例#16
0
        public void CheckPendingProofs()
        {
            Logger.Information("Connecting to node ...");
            var node = Node.Connect(Network.Main, new IPEndPoint(IPAddress.Parse(_nodes), 16178));

            node.VersionHandshake();
            Logger.Information("Connected..");

            Logger.Information("Checking pending proofs");
            var proofs = DataService.GetProofs(new ProofFilter
            {
                Statuses = new[] { Constants.ProofStatus.ProofPending }
            }).Proofs;

            if (proofs != null)
            {
                Logger.Information($"Total pending proof payments {proofs.Count()}");
                var savedProofs = new List <Proof>();
                foreach (var proof in proofs)
                {
                    var privateKey = GetSecret(proof.PayAddress.KeyPath);
                    var secret     = new BitcoinSecret(privateKey.PrivateKey, Network.Main);

                    var sender        = _publicKey.Derive(new KeyPath("0/0"));
                    var senderAddress = sender.PubKey.GetAddress(Network.Main);
                    Logger.Information($"Checking balance { proof.PayAddress.Address }");
                    var address      = new BitcoinPubKeyAddress(proof.PayAddress.Address, Network.Main);
                    var scriptPubKey = address.ScriptPubKey.ToString();
                    var unspents     = GetUnspentTransactions(address).ToList();
                    //foreach (var unspent in unspents)
                    //{
                    //    Logger.Information($"-> {unspent.Hash}");
                    //}
                    var unspentTransaction = unspents.LastOrDefault(x => x.IndexedOutputs.Any(o => o.ScriptPubKey == scriptPubKey));

                    if (unspentTransaction != null)
                    {
                        Logger.Information($"Unspent {unspentTransaction.Hash}");
                        var outputs = unspentTransaction.IndexedOutputs.Where(x => x.ScriptPubKey == scriptPubKey).ToList();
                        Logger.Information($"Total outputs found {outputs.Count}");
                        var transaction = new Transaction();
                        var balance     = 0m;
                        var fee         = 0.0001m;
                        var docFee      = 0.00001m;

                        foreach (var output in outputs)
                        {
                            if (output.Value > 0)
                            {
                                balance += output.Value;
                                var txin = new TxIn
                                {
                                    PrevOut   = new OutPoint(new uint256(unspentTransaction.Hash), output.Index),
                                    ScriptSig = secret.ScriptPubKey
                                };
                                transaction.Inputs.Add(txin);
                            }
                        }

                        Logger.Information($"Total inputs { transaction.Inputs.Count()} from prev ouputs {outputs.Count()} with balance {balance}");

                        if (balance > 0)
                        {
                            var amount = balance - (docFee + fee);


                            var docScriptKey = GetHashScript(proof.Hash);
                            Logger.Information($"docScriptKey -> {docScriptKey},  Length -> {docScriptKey.ToBytes().Length}");

                            var docOutput = new TxOut();
                            docOutput.Value        = new Money(docFee, MoneyUnit.BTC);
                            docOutput.ScriptPubKey = docScriptKey;
                            transaction.AddOutput(docOutput);


                            var changeOutput = new TxOut();
                            changeOutput.Value        = new Money(amount, MoneyUnit.BTC);
                            changeOutput.ScriptPubKey = senderAddress.ScriptPubKey;
                            transaction.AddOutput(changeOutput);

                            var isStandard = StandardScripts.IsStandardTransaction(transaction);
                            Logger.Information($"Standard -> {isStandard}");

                            transaction.Sign(secret, false);

                            Logger.Information($"{transaction}");



                            node.SendMessage(new InvPayload(transaction));
                            node.SendMessage(new TxPayload(transaction));


                            proof.Status = Constants.ProofStatus.ConfirmPending;
                            savedProofs.Add(proof);
                        }
                    }
                }

                if (savedProofs.Any())
                {
                    Logger.Information("Saving pending proofs");
                    DataService.SaveProofs(savedProofs);
                }
            }
            else
            {
                Logger.Information("No pending proof payments found");
            }
            Logger.Information("Check pending proof finished ");

            Thread.Sleep(4000);
            node.Disconnect();
            Logger.Information("Node disconnecting...");
        }
        public static ScriptOutputInfo GetAddressInternal(Network network, Script script)
        {
            ScriptTemplate template = StandardScripts.GetTemplateFromScriptPubKey(script);

            if (template == null)
            {
                return(null);
            }

            if (template.Type == TxOutType.TX_NONSTANDARD ||
                template.Type == TxOutType.TX_NULL_DATA ||
                template.Type == TxOutType.TX_MULTISIG)
            {
                return(new ScriptOutputInfo {
                    ScriptType = template.Type.ToString()
                });
            }

            if (template.Type == TxOutType.TX_PUBKEY)
            {
                PubKey[] pubkeys = script.GetDestinationPublicKeys(network);
                return(new ScriptOutputInfo
                {
                    ScriptType = template.Type.ToString(),
                    Addresses = new[] { pubkeys[0].GetAddress(network).ToString() }
                });
            }

            if (template.Type == TxOutType.TX_PUBKEYHASH ||
                template.Type == TxOutType.TX_SCRIPTHASH ||
                template.Type == TxOutType.TX_SEGWIT)
            {
                BitcoinAddress bitcoinAddress = script.GetDestinationAddress(network);
                if (bitcoinAddress != null)
                {
                    return(new ScriptOutputInfo
                    {
                        ScriptType = template.Type.ToString(),
                        Addresses = new[] { bitcoinAddress.ToString() }
                    });
                }
            }

            if (template.Type == TxOutType.TX_COLDSTAKE)
            {
                if (ColdStakingScriptTemplate.Instance.ExtractScriptPubKeyParameters(script, out KeyId hotPubKeyHash, out KeyId coldPubKeyHash))
                {
                    // We want to index based on both the cold and hot key
                    return(new ScriptOutputInfo
                    {
                        ScriptType = template.Type.ToString(),
                        Addresses = new[] { coldPubKeyHash.GetAddress(network).ToString(), hotPubKeyHash.GetAddress(network).ToString() }
                    });
                }

                return(new ScriptOutputInfo {
                    ScriptType = template.Type.ToString()
                });
            }

            return(null);
        }
示例#18
0
        private IEnumerable <SyncTransactionAddressItem> SelectAddressWithPool(SyncBlockInfo current, string address, bool availableOnly)
        {
            FilterDefinitionBuilder <MapTransactionAddress> builder = Builders <MapTransactionAddress> .Filter;
            var addressFiler = new List <string> {
                address
            };
            FilterDefinition <MapTransactionAddress> filter = builder.AnyIn(transactionAddress => transactionAddress.Addresses, addressFiler);

            if (availableOnly)
            {
                // we only want spendable transactions
                filter = filter & builder.Eq(info => info.SpendingTransactionId, null);
            }

            watch.Restart();

            SortDefinition <MapTransactionAddress> sort = Builders <MapTransactionAddress> .Sort.Descending(info => info.BlockIndex);

            var addrs = MapTransactionAddress.Find(filter).Sort(sort).ToList();

            watch.Stop();

            log.LogInformation($"Select: Seconds = {watch.Elapsed.TotalSeconds} - UnspentOnly = {availableOnly} - Addr = {address} - Items = {addrs.Count()}");

            // this creates a copy of the collection (to avoid thread issues)
            ICollection <Transaction> pool = MemoryTransactions.Values;

            if (pool.Any())
            {
                // mark trx in output as spent if they exist in the pool
                List <MapTransactionAddress> addrsupdate = addrs;
                GetPoolOutputs(pool).ForEach(f =>
                {
                    MapTransactionAddress adr = addrsupdate.FirstOrDefault(a => a.TransactionId == f.Item1.PrevOut.Hash.ToString() && a.Index == f.Item1.PrevOut.N);
                    if (adr != null)
                    {
                        adr.SpendingTransactionId = f.Item2;
                    }
                });

                // if only spendable transactions are to be returned we need to remove
                // any that have been marked as spent by a transaction in the pool
                if (availableOnly)
                {
                    addrs = addrs.Where(d => d.SpendingTransactionId == null).ToList();
                }

                // add all pool transactions to main output
                var paddr = PoolToMapTransactionAddress(pool, address).ToList();
                addrs = addrs.OrderByDescending(s => s.BlockIndex).Concat(paddr).ToList();
            }

            // map to return type and calculate confirmations
            return(addrs.Select(s => new SyncTransactionAddressItem
            {
                Address = address,
                Index = s.Index,
                TransactionHash = s.TransactionId,
                BlockIndex = s.BlockIndex == -1 ? default(long?) : s.BlockIndex,
                Value = s.Value,
                Confirmations = s.BlockIndex == -1 ? 0 : current.BlockIndex - s.BlockIndex + 1,
                SpendingTransactionHash = s.SpendingTransactionId,
                SpendingBlockIndex = s.SpendingBlockIndex,
                CoinBase = s.CoinBase,
                CoinStake = s.CoinStake,
                ScriptHex = new Script(Encoders.Hex.DecodeData(s.ScriptHex)).ToString(),
                Type = StandardScripts.GetTemplateFromScriptPubKey(new Script(Encoders.Hex.DecodeData(s.ScriptHex)))?.Type.ToString(),
                Time = s.BlockIndex == -1 ? UnixUtils.DateToUnixTimestamp(DateTime.UtcNow) : current.BlockTime
            }));
        }
示例#19
0
        public SyncTransactionItems TransactionItemsGet(string transactionId)
        {
            NBitcoin.Transaction transaction;

            // Try to find the trx in disk
            SyncRawTransaction rawtrx = TransactionGetByHash(transactionId);

            if (rawtrx == null)
            {
                BitcoinClient client = CryptoClientFactory.Create(syncConnection.ServerDomain, syncConnection.RpcAccessPort, syncConnection.User, syncConnection.Password, syncConnection.Secure);

                Client.Types.DecodedRawTransaction res = client.GetRawTransactionAsync(transactionId, 0).Result;

                if (res.Hex == null)
                {
                    return(null);
                }

                transaction = syncConnection.Network.Consensus.ConsensusFactory.CreateTransaction(res.Hex);
                transaction.PrecomputeHash(false, true);
            }
            else
            {
                transaction = syncConnection.Network.Consensus.ConsensusFactory.CreateTransaction(rawtrx.RawTransaction);
                transaction.PrecomputeHash(false, true);
            }

            var ret = new SyncTransactionItems
            {
                RBF         = transaction.RBF,
                LockTime    = transaction.LockTime.ToString(),
                Version     = transaction.Version,
                IsCoinbase  = transaction.IsCoinBase,
                IsCoinstake = syncConnection.Network.Consensus.IsProofOfStake && transaction.IsCoinStake,
                Inputs      = transaction.Inputs.Select(v => new SyncTransactionItemInput
                {
                    PreviousTransactionHash = v.PrevOut.Hash.ToString(),
                    PreviousIndex           = (int)v.PrevOut.N,
                    WitScript    = v.WitScript.ToScript().ToHex(),
                    ScriptSig    = v.ScriptSig.ToHex(),
                    SequenceLock = v.Sequence.ToString(),
                }).ToList(),
                Outputs = transaction.Outputs.Select((output, index) => new SyncTransactionItemOutput
                {
                    Address      = ScriptToAddressParser.GetAddress(syncConnection.Network, output.ScriptPubKey)?.FirstOrDefault(),
                    Index        = index,
                    Value        = output.Value,
                    OutputType   = StandardScripts.GetTemplateFromScriptPubKey(output.ScriptPubKey)?.Type.ToString(),
                    ScriptPubKey = output.ScriptPubKey.ToHex()
                }).ToList()
            };


            // try to fetch spent outputs
            foreach (SyncTransactionItemOutput output in ret.Outputs)
            {
                output.SpentInTransaction = GetSpendingTransaction(transactionId, output.Index);
            }

            return(ret);
        }
示例#20
0
 public ScriptTemplate FindTemplate()
 {
     return(StandardScripts.GetTemplateFromScriptPubKey(this));
 }
        private void CheckStandardTransaction(MempoolValidationContext context, bool witnessEnabled)
        {
            // TODO: Implement Witness Code

            var tx = context.Transaction;

            if (tx.Version > this.consensusValidator.ConsensusOptions.MAX_STANDARD_VERSION || tx.Version < 1)
            {
                context.State.Fail(MempoolErrors.Version).Throw();
            }

            // Extremely large transactions with lots of inputs can cost the network
            // almost as much to process as they cost the sender in fees, because
            // computing signature hashes is O(ninputs*txsize). Limiting transactions
            // to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
            var sz = GetTransactionWeight(tx, this.consensusValidator.ConsensusOptions);

            if (sz >= this.consensusValidator.ConsensusOptions.MAX_STANDARD_TX_WEIGHT)
            {
                context.State.Fail(MempoolErrors.TxSize).Throw();
            }

            foreach (var txin in tx.Inputs)
            {
                // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
                // keys (remember the 520 byte limit on redeemScript size). That works
                // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
                // bytes of scriptSig, which we round off to 1650 bytes for some minor
                // future-proofing. That's also enough to spend a 20-of-20
                // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
                // considered standard.
                if (txin.ScriptSig.Length > 1650)
                {
                    context.State.Fail(MempoolErrors.ScriptsigSize).Throw();
                }

                if (!txin.ScriptSig.IsPushOnly)
                {
                    context.State.Fail(MempoolErrors.ScriptsigNotPushonly).Throw();
                }
            }

            int dataOut = 0;

            foreach (var txout in tx.Outputs)
            {
                var script = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey);
                if (script == null)                 //!::IsStandard(txout.scriptPubKey, whichType, witnessEnabled))
                {
                    context.State.Fail(MempoolErrors.Scriptpubkey).Throw();
                }

                if (script.Type == TxOutType.TX_NULL_DATA)
                {
                    dataOut++;
                }
                // TODO: fIsBareMultisigStd
                //else if ((script == PayToMultiSigTemplate.Instance))  (!fIsBareMultisigStd))
                //{
                //	context.State.Fail(new MempoolError(MempoolErrors.RejectNonstandard, "bare-multisig")).Throw();
                //}
                else if (txout.IsDust(MinRelayTxFee))
                {
                    context.State.Fail(MempoolErrors.Dust).Throw();
                }
            }

            // only one OP_RETURN txout is permitted
            if (dataOut > 1)
            {
                context.State.Fail(MempoolErrors.MultiOpReturn).Throw();
            }
        }
 public ColdStakingControllerTest() : base(KnownNetworks.StratisMain)
 {
     // Register the cold staking script template.
     StandardScripts.RegisterStandardScriptTemplate(ColdStakingScriptTemplate.Instance);
 }
        public ColdStakingManagerTest(WalletFixture walletFixture)
        {
            this.walletFixture = walletFixture;

            StandardScripts.RegisterStandardScriptTemplate(ColdStakingScriptTemplate.Instance);
        }
示例#24
0
        private static void ConfigureServiceProvider()
        {
            var mapperConfiguration = new MapperConfiguration(configurationExpression =>
            {
                configurationExpression.AddProfile(new DomainObjectsProfile());
            });
            var serviceCollection = new ServiceCollection();

            serviceCollection
            .AddSingleton(provider => mapperConfiguration.CreateMapper())
            .AddSingleton <IConfiguration>(p =>
                                           new ConfigurationBuilder()
                                           .SetBasePath(Directory.GetCurrentDirectory())
                                           .AddJsonFile("appsettings.json", true, true)
                                           .Build()
                                           )
            .AddScoped(typeof(IWalletRpcService <>), typeof(WalletRpcService <>))
            .AddScoped <IRpcBlockCountService, RpcBlockCountService>()
            .AddScoped <IRpcBlockHashService, RpcBlockHashService>()
            .AddScoped <IRpcBlockService, RpcBlockService>()
            .AddScoped <IRpcTransactionService, RpcTransactionService>()
            .AddScoped <IDbConnectionFactory>(provider =>
            {
                var configuration = provider.GetService <IConfiguration>();
                return(new DbConnectionFactory
                {
                    ConnectionString = configuration.GetConnectionString("SolarisExplorerDatabase")
                });
            })
            .AddScoped(provider =>
            {
                var dbConnectionFactory = provider.GetService <IDbConnectionFactory>();
                return(dbConnectionFactory.CreateConnection());
            })
            .AddScoped <IBlockRepository, BlockRepository>()
            .AddScoped <ITransactionRepository, TransactionRepository>()
            .AddScoped <ITransactionOutputRepository, TransactionOutputRepository>()
            .AddScoped <ITransactionInputRepository, TransactionInputRepository>()
            .AddScoped <IClearAllDataRepository, ClearAllDataRepository>();



            serviceCollection.AddHttpClient("Daemon", (provider, client) =>
            {
                var configuration = provider.GetService <IConfiguration>();
                var daemonSection = configuration.GetSection("Daemon");
                var username      = daemonSection.GetValue <string>("Username");
                var password      = daemonSection.GetValue <string>("Password");
                var url           = daemonSection.GetValue <string>("Url");

                client.BaseAddress = new Uri(url);
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}")));
                client.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.5");
            });


            serviceCollection.AddHttpClient("FrontendNotification", (provider, client) =>
            {
                var configuration = provider.GetService <IConfiguration>();
                var frontendNotificationSection = configuration.GetSection("FrontendNotification");

                if (frontendNotificationSection == null || !frontendNotificationSection.GetValue <bool>("IsEnabled"))
                {
                    return;
                }

                var token = frontendNotificationSection.GetValue <string>("Token");
                var url   = frontendNotificationSection.GetValue <string>("Url");

                client.BaseAddress = new Uri(url);
                client.DefaultRequestHeaders.Add("Token", token);
            });

            _serviceProvider = serviceCollection.BuildServiceProvider();

            StandardScripts.RegisterStandardScriptTemplate(ColdStakingScriptTemplate.Instance);
        }