diff --git a/src/Blockcore/Consensus/ScriptAddressReader.cs b/src/Blockcore/Consensus/ScriptAddressReader.cs
index 80ca7d3a7..0950f5a4f 100644
--- a/src/Blockcore/Consensus/ScriptAddressReader.cs
+++ b/src/Blockcore/Consensus/ScriptAddressReader.cs
@@ -9,29 +9,36 @@ namespace Blockcore.Consensus
public class ScriptAddressReader : IScriptAddressReader
{
///
- public string GetAddressFromScriptPubKey(Network network, Script script)
+ public ScriptAddressResult GetAddressFromScriptPubKey(Network network, Script script)
{
ScriptTemplate scriptTemplate = network.StandardScriptsRegistry.GetTemplateFromScriptPubKey(script);
- string destinationAddress = null;
+ var destinationAddress = new ScriptAddressResult();
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();
+ destinationAddress.Address = 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();
+ destinationAddress.Address = script.GetDestinationAddress(network).ToString();
break;
+
case TxOutType.TX_SCRIPTHASH:
- destinationAddress = script.GetDestinationAddress(network).ToString();
+ destinationAddress.Address = script.GetDestinationAddress(network).ToString();
+ break;
+
+ case TxOutType.TX_COLDSTAKE:
+ destinationAddress = this.GetColdStakeAddresses(network, script);
break;
+
case TxOutType.TX_SEGWIT:
- destinationAddress = script.GetDestinationAddress(network).ToString();
+ destinationAddress.Address = script.GetDestinationAddress(network).ToString();
break;
+
case TxOutType.TX_NONSTANDARD:
case TxOutType.TX_MULTISIG:
case TxOutType.TX_NULL_DATA:
@@ -40,5 +47,15 @@ public string GetAddressFromScriptPubKey(Network network, Script script)
return destinationAddress;
}
+
+ public ScriptAddressResult GetColdStakeAddresses(Network network, Script script)
+ {
+ var destinationAddressResult = script.GetColdStakeDestinationAddress(network);
+ return new ScriptAddressResult()
+ {
+ HotAddress = destinationAddressResult.hotAddress.ToString(),
+ ColdAddress = destinationAddressResult.coldAddress.ToString()
+ };
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Blockcore/Consensus/ScriptAddressResult.cs b/src/Blockcore/Consensus/ScriptAddressResult.cs
new file mode 100644
index 000000000..9aa1dede4
--- /dev/null
+++ b/src/Blockcore/Consensus/ScriptAddressResult.cs
@@ -0,0 +1,42 @@
+namespace Blockcore.Consensus
+{
+ ///
+ /// The script result address.
+ ///
+ public class ScriptAddressResult
+ {
+ ///
+ /// Will return the script public address if exists, Otherwise returns
+ ///
+ public static implicit operator string(ScriptAddressResult scriptAddressResult)
+ {
+ return scriptAddressResult.Address.ToString();
+ }
+
+ ///
+ /// If Address, Hot and Cold addresses are all empty, it will return true, otherwise false.
+ ///
+ public bool IsNullOrEmpty()
+ {
+ return string.IsNullOrEmpty(this.Address) &&
+ string.IsNullOrEmpty(this.HotAddress) &&
+ string.IsNullOrEmpty(this.ColdAddress);
+ }
+
+ ///
+ /// Will return the script public address if exists, Otherwise returns
+ ///
+ public string Address { get; set; } = string.Empty;
+
+ ///
+ /// Will return the script hot public address if exists, Otherwise returns
+ ///
+ public string HotAddress { get; set; } = string.Empty;
+
+ ///
+ /// Will return the script cold public address if exists, Otherwise returns
+ ///
+ public string ColdAddress { get; set; } = string.Empty;
+
+ }
+}
diff --git a/src/Features/Blockcore.Features.ColdStaking/ColdStakingScriptSigParameters.cs b/src/Blockcore/Consensus/ScriptInfo/ColdStakingScriptSigParameters.cs
similarity index 82%
rename from src/Features/Blockcore.Features.ColdStaking/ColdStakingScriptSigParameters.cs
rename to src/Blockcore/Consensus/ScriptInfo/ColdStakingScriptSigParameters.cs
index 94f1daa4a..0fdc542a5 100644
--- a/src/Features/Blockcore.Features.ColdStaking/ColdStakingScriptSigParameters.cs
+++ b/src/Blockcore/Consensus/ScriptInfo/ColdStakingScriptSigParameters.cs
@@ -1,8 +1,7 @@
-using Blockcore.Consensus.ScriptInfo;
-using Blockcore.Consensus.TransactionInfo;
+using Blockcore.Consensus.TransactionInfo;
using NBitcoin;
-namespace Blockcore.Features.ColdStaking
+namespace Blockcore.Consensus.ScriptInfo
{
///
/// The scriptSig parameters used for cold staking script.
diff --git a/src/Features/Blockcore.Features.ColdStaking/ColdStakingScriptTemplate.cs b/src/Blockcore/Consensus/ScriptInfo/ColdStakingScriptTemplate.cs
similarity index 99%
rename from src/Features/Blockcore.Features.ColdStaking/ColdStakingScriptTemplate.cs
rename to src/Blockcore/Consensus/ScriptInfo/ColdStakingScriptTemplate.cs
index 8a7b6f563..87be52743 100644
--- a/src/Features/Blockcore.Features.ColdStaking/ColdStakingScriptTemplate.cs
+++ b/src/Blockcore/Consensus/ScriptInfo/ColdStakingScriptTemplate.cs
@@ -1,15 +1,13 @@
using System;
using System.Linq;
-using Blockcore.Consensus;
using Blockcore.Consensus.BlockInfo;
-using Blockcore.Consensus.ScriptInfo;
using Blockcore.Consensus.TransactionInfo;
using Blockcore.Networks;
using Blockcore.Utilities;
using NBitcoin;
using static Blockcore.Consensus.ScriptInfo.OpcodeType;
-namespace Blockcore.Features.ColdStaking
+namespace Blockcore.Consensus.ScriptInfo
{
///
/// Script template for the cold staking script.
diff --git a/src/Blockcore/Consensus/ScriptInfo/Script.cs b/src/Blockcore/Consensus/ScriptInfo/Script.cs
index c7040987c..aeab1a54f 100644
--- a/src/Blockcore/Consensus/ScriptInfo/Script.cs
+++ b/src/Blockcore/Consensus/ScriptInfo/Script.cs
@@ -1011,6 +1011,24 @@ public BitcoinAddress GetDestinationAddress(Network network)
return dest == null ? null : dest.GetAddress(network);
}
+ ///
+ /// Extract ColdStakingScript addresses from scriptPubKey
+ ///
+ ///
+ /// Both hot and cold BitcoinAddress addresses
+ public (BitcoinAddress hotAddress, BitcoinAddress coldAddress) GetColdStakeDestinationAddress(Network network)
+ {
+ bool hasAddresses = ColdStakingScriptTemplate.Instance.ExtractScriptPubKeyParameters(this, out KeyId hotKeyId, out KeyId coldKeyId);
+ if (hasAddresses)
+ {
+ return (hotKeyId.GetAddress(network), coldKeyId.GetAddress(network));
+ }
+ else
+ {
+ return (null, null);
+ }
+ }
+
///
/// Extract P2SH/P2PH/P2WSH/P2WPKH id from scriptPubKey
///
diff --git a/src/Blockcore/Interfaces/IScriptAddressReader.cs b/src/Blockcore/Interfaces/IScriptAddressReader.cs
index 28458058c..5b0549c92 100644
--- a/src/Blockcore/Interfaces/IScriptAddressReader.cs
+++ b/src/Blockcore/Interfaces/IScriptAddressReader.cs
@@ -1,4 +1,5 @@
-using Blockcore.Consensus.ScriptInfo;
+using Blockcore.Consensus;
+using Blockcore.Consensus.ScriptInfo;
using Blockcore.Networks;
using NBitcoin;
@@ -12,9 +13,6 @@ public interface IScriptAddressReader
///
/// Extracts an address from a given Script, if available. Otherwise returns
///
- ///
- ///
- ///
- string GetAddressFromScriptPubKey(Network network, Script script);
+ ScriptAddressResult GetAddressFromScriptPubKey(Network network, Script script);
}
-}
+}
\ No newline at end of file
diff --git a/src/Features/Blockcore.Features.BlockStore/AddressIndexing/AddressIndexer.cs b/src/Features/Blockcore.Features.BlockStore/AddressIndexing/AddressIndexer.cs
index a337b3f78..194ff56e9 100644
--- a/src/Features/Blockcore.Features.BlockStore/AddressIndexing/AddressIndexer.cs
+++ b/src/Features/Blockcore.Features.BlockStore/AddressIndexing/AddressIndexer.cs
@@ -447,15 +447,22 @@ private bool ProcessBlock(Block block, ChainedHeader header)
if (amountSpent == 0)
continue;
- string address = this.scriptAddressReader.GetAddressFromScriptPubKey(this.network, new Script(consumedOutputData.ScriptPubKeyBytes));
+ var address = this.scriptAddressReader.GetAddressFromScriptPubKey(this.network, new Script(consumedOutputData.ScriptPubKeyBytes));
- if (string.IsNullOrEmpty(address))
+ if (address.IsNullOrEmpty())
{
// This condition need not be logged, as the address reader should be aware of all possible address formats already.
continue;
}
- this.ProcessBalanceChangeLocked(header.Height, address, amountSpent, false);
+ if (address.Address != string.Empty)
+ this.ProcessBalanceChangeLocked(header.Height, address.Address, amountSpent, false);
+
+ if (address.HotAddress != string.Empty)
+ this.ProcessBalanceChangeLocked(header.Height, address.HotAddress, amountSpent, false);
+
+ if (address.ColdAddress != string.Empty)
+ this.ProcessBalanceChangeLocked(header.Height, address.ColdAddress, amountSpent, false);
}
// Process outputs.
@@ -469,16 +476,23 @@ private bool ProcessBlock(Block block, ChainedHeader header)
if (amountReceived == 0 || txOut.IsEmpty || txOut.ScriptPubKey.IsUnspendable)
continue;
- string address = this.scriptAddressReader.GetAddressFromScriptPubKey(this.network, txOut.ScriptPubKey);
+ var address = this.scriptAddressReader.GetAddressFromScriptPubKey(this.network, txOut.ScriptPubKey);
- if (string.IsNullOrEmpty(address))
+ if (address.IsNullOrEmpty())
{
// This condition need not be logged, as the address reader should be aware of all
// possible address formats already.
continue;
}
- this.ProcessBalanceChangeLocked(header.Height, address, amountReceived, true);
+ if (address.Address != string.Empty)
+ this.ProcessBalanceChangeLocked(header.Height, address.Address, amountReceived, true);
+
+ if (address.HotAddress != string.Empty)
+ this.ProcessBalanceChangeLocked(header.Height, address.HotAddress, amountReceived, true);
+
+ if (address.ColdAddress != string.Empty)
+ this.ProcessBalanceChangeLocked(header.Height, address.ColdAddress, amountReceived, true);
}
}
diff --git a/src/Features/Blockcore.Features.ColdStaking/ColdStakingFeature.cs b/src/Features/Blockcore.Features.ColdStaking/ColdStakingFeature.cs
index 510c08121..f3f6e28c4 100644
--- a/src/Features/Blockcore.Features.ColdStaking/ColdStakingFeature.cs
+++ b/src/Features/Blockcore.Features.ColdStaking/ColdStakingFeature.cs
@@ -9,6 +9,7 @@
using Blockcore.Configuration.Logging;
using Blockcore.Connection;
using Blockcore.Connection.Broadcasting;
+using Blockcore.Consensus.ScriptInfo;
using Blockcore.Features.BlockStore;
using Blockcore.Features.MemoryPool;
using Blockcore.Features.RPC;