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); }
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); }
/// <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]); } }
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)); }
/// <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); }
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)); } } } }
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); }
/// <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); }
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); }
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 })); }
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); }
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); }
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); }