Commit 2cfa0f42 authored by Pavel Pavlov's avatar Pavel Pavlov

Modify project NBitcoin

parent 2edbb663
......@@ -16,7 +16,7 @@ namespace NBitcoin
public class Scope : IDisposable
{
Action close;
private Action close;
public Scope(Action open, Action close)
{
this.close = close;
......@@ -27,7 +27,7 @@ namespace NBitcoin
public void Dispose()
{
close();
this.close();
}
#endregion
......@@ -48,7 +48,7 @@ namespace NBitcoin
// TODO: Make NetworkOptions required in the constructors of this class.
public partial class BitcoinStream
{
int maxArraySize = 1024 * 1024;
private int maxArraySize = 1024 * 1024;
public int MaxArraySize
{
get
......@@ -62,7 +62,7 @@ namespace NBitcoin
}
//ReadWrite<T>(ref T data)
static MethodInfo readWriteTyped;
private static MethodInfo readWriteTyped;
static BitcoinStream()
{
readWriteTyped = typeof(BitcoinStream)
......@@ -95,6 +95,7 @@ namespace NBitcoin
public BitcoinStream(Stream inner, bool serializing)
{
this.ConsensusFactory = new DefaultConsensusFactory();
this.serializing = serializing;
this.inner = inner;
}
......@@ -138,12 +139,12 @@ namespace NBitcoin
{
if (this.Serializing)
{
VarString str = new VarString(bytes);
var str = new VarString(bytes);
str.ReadWrite(this);
}
else
{
VarString str = new VarString();
var str = new VarString();
str.ReadWrite(this);
bytes = str.GetString(true);
}
......@@ -193,12 +194,14 @@ namespace NBitcoin
public void ReadWrite<T>(ref T data) where T : IBitcoinSerializable
{
var obj = data;
T obj = data;
if (obj == null)
{
if (!this.ConsensusFactory.TryCreateNew<T>(out obj))
obj = this.ConsensusFactory.TryCreateNew<T>();
if (obj == null)
obj = Activator.CreateInstance<T>();
}
obj.ReadWrite(this);
if (!this.Serializing)
data = obj;
......@@ -220,7 +223,7 @@ namespace NBitcoin
where TList : List<TItem>, new()
where TItem : IBitcoinSerializable, new()
{
var dataArray = data == null ? null : data.ToArray();
TItem[] dataArray = data == null ? null : data.ToArray();
if (this.Serializing && dataArray == null)
{
......@@ -241,7 +244,7 @@ namespace NBitcoin
public void ReadWrite(ref byte[] arr)
{
this.ReadWriteBytes(ref arr);
ReadWriteBytes(ref arr);
}
public void ReadWrite(ref byte[] arr, int offset, int count)
......@@ -265,7 +268,7 @@ namespace NBitcoin
{
var bytes = new byte[size];
for(int i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
bytes[i] = (byte)(value >> i * 8);
}
......@@ -277,7 +280,7 @@ namespace NBitcoin
ulong valueTemp = 0;
for (int i = 0; i < bytes.Length; i++)
{
var v = (ulong)bytes[i];
ulong v = (ulong)bytes[i];
valueTemp += v << (i * 8);
}
value = valueTemp;
......@@ -300,7 +303,7 @@ namespace NBitcoin
}
else
{
var readen = this.Inner.ReadEx(data, offset, count, this.ReadCancellationToken);
int readen = this.Inner.ReadEx(data, offset, count, this.ReadCancellationToken);
if (readen == 0)
throw new EndOfStreamException("No more byte to read");
this.Counter.AddRead(readen);
......@@ -328,7 +331,7 @@ namespace NBitcoin
}
else
{
var readen = this.Inner.ReadByte();
int readen = this.Inner.ReadByte();
if (readen == -1)
throw new EndOfStreamException("No more byte to read");
data = (byte)readen;
......@@ -344,7 +347,7 @@ namespace NBitcoin
public IDisposable BigEndianScope()
{
var old = this.IsBigEndian;
bool old = this.IsBigEndian;
return new Scope(() =>
{
this.IsBigEndian = true;
......@@ -355,7 +358,7 @@ namespace NBitcoin
});
}
ProtocolVersion protocolVersion = ProtocolVersion.PROTOCOL_VERSION;
private ProtocolVersion protocolVersion = ProtocolVersion.PROTOCOL_VERSION;
public ProtocolVersion ProtocolVersion
{
get
......@@ -368,7 +371,7 @@ namespace NBitcoin
}
}
TransactionOptions transactionSupportedOptions = TransactionOptions.All;
private TransactionOptions transactionSupportedOptions = TransactionOptions.All;
public TransactionOptions TransactionOptions
{
get
......@@ -388,7 +391,7 @@ namespace NBitcoin
public IDisposable ProtocolVersionScope(ProtocolVersion version)
{
var old = this.ProtocolVersion;
ProtocolVersion old = this.ProtocolVersion;
return new Scope(() =>
{
this.ProtocolVersion = version;
......@@ -419,7 +422,7 @@ namespace NBitcoin
public IDisposable SerializationTypeScope(SerializationType value)
{
var old = this.Type;
SerializationType old = this.Type;
return new Scope(() =>
{
this.Type = value;
......
......@@ -23,16 +23,16 @@ namespace NBitcoin
}
// 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
const uint MAX_BLOOM_FILTER_SIZE = 36000; // bytes
const uint MAX_HASH_FUNCS = 50;
const decimal LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455M;
const decimal LN2 = 0.6931471805599453094172321214581765680755001343602552M;
private const uint MAX_BLOOM_FILTER_SIZE = 36000; // bytes
private const uint MAX_HASH_FUNCS = 50;
private const decimal LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455M;
private const decimal LN2 = 0.6931471805599453094172321214581765680755001343602552M;
byte[] vData;
uint nHashFuncs;
uint nTweak;
byte nFlags;
private byte[] vData;
private uint nHashFuncs;
private uint nTweak;
private byte nFlags;
private bool isFull = false;
private bool isEmpty;
......@@ -48,49 +48,50 @@ namespace NBitcoin
// The ideal size for a bloom filter with a given number of elements and false positive rate is:
// - nElements * log(fp rate) / ln(2)^2
// We ignore filter parameters which will create a bloom filter larger than the protocol limits
vData = new byte[Math.Min((uint)(-1 / LN2SQUARED * nElements * (decimal)Math.Log(nFPRate)), MAX_BLOOM_FILTER_SIZE) / 8];
this.vData = new byte[Math.Min((uint)(-1 / LN2SQUARED * nElements * (decimal)Math.Log(nFPRate)), MAX_BLOOM_FILTER_SIZE) / 8];
//vData(min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
// The ideal number of hash functions is filter size * ln(2) / number of elements
// Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
// See http://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
this.nHashFuncs = Math.Min((uint)(vData.Length * 8 / nElements * LN2), MAX_HASH_FUNCS);
this.nHashFuncs = Math.Min((uint)(this.vData.Length * 8 / nElements * LN2), MAX_HASH_FUNCS);
this.nTweak = nTweakIn;
this.nFlags = (byte)nFlagsIn;
}
uint Hash(uint nHashNum, byte[] vDataToHash)
private uint Hash(uint nHashNum, byte[] vDataToHash)
{
// 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
return (uint)(Hashes.MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (vData.Length * 8));
return (uint)(Hashes.MurmurHash3(nHashNum * 0xFBA4C795 + this.nTweak, vDataToHash) % (this.vData.Length * 8));
}
public void Insert(byte[] vKey)
{
if(isFull)
if(this.isFull)
return;
for(uint i = 0; i < nHashFuncs; i++)
for(uint i = 0; i < this.nHashFuncs; i++)
{
uint nIndex = Hash(i, vKey);
// Sets bit nIndex of vData
vData[nIndex >> 3] |= (byte)(1 << (7 & (int)nIndex));
this.vData[nIndex >> 3] |= (byte)(1 << (7 & (int)nIndex));
}
isEmpty = false;
this.isEmpty = false;
}
public bool Contains(byte[] vKey)
{
if(isFull)
if(this.isFull)
return true;
if(isEmpty)
if(this.isEmpty)
return false;
for(uint i = 0; i < nHashFuncs; i++)
for(uint i = 0; i < this.nHashFuncs; i++)
{
uint nIndex = Hash(i, vKey);
// Checks bit nIndex of vData
if((vData[nIndex >> 3] & (byte)(1 << (7 & (int)nIndex))) == 0)
if((this.vData[nIndex >> 3] & (byte)(1 << (7 & (int)nIndex))) == 0)
return false;
}
return true;
......@@ -125,17 +126,17 @@ namespace NBitcoin
public bool IsWithinSizeConstraints()
{
return vData.Length <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
return this.vData.Length <= MAX_BLOOM_FILTER_SIZE && this.nHashFuncs <= MAX_HASH_FUNCS;
}
#region IBitcoinSerializable Members
public void ReadWrite(BitcoinStream stream)
{
stream.ReadWriteAsVarString(ref vData);
stream.ReadWrite(ref nHashFuncs);
stream.ReadWrite(ref nTweak);
stream.ReadWrite(ref nFlags);
stream.ReadWriteAsVarString(ref this.vData);
stream.ReadWrite(ref this.nHashFuncs);
stream.ReadWrite(ref this.nTweak);
stream.ReadWrite(ref this.nFlags);
}
#endregion
......@@ -146,13 +147,13 @@ namespace NBitcoin
{
if(tx == null)
throw new ArgumentNullException("tx");
var hash = tx.GetHash();
uint256 hash = tx.GetHash();
bool fFound = false;
// Match if the filter contains the hash of tx
// for finding tx when they appear in a block
if(isFull)
if(this.isFull)
return true;
if(isEmpty)
if(this.isEmpty)
return false;
if(Contains(hash))
fFound = true;
......@@ -169,11 +170,11 @@ namespace NBitcoin
if(op.PushData != null && op.PushData.Length != 0 && Contains(op.PushData))
{
fFound = true;
if((nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_ALL)
if((this.nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_ALL)
Insert(new OutPoint(hash, i));
else if((nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_P2PUBKEY_ONLY)
else if((this.nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_P2PUBKEY_ONLY)
{
var template = StandardScripts.GetTemplateFromScriptPubKey(Network.Main, txout.ScriptPubKey); // this is only valid for Bitcoin.
ScriptTemplate template = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey); // this is only valid for Bitcoin.
if(template != null &&
(template.Type == TxOutType.TX_PUBKEY || template.Type == TxOutType.TX_MULTISIG))
Insert(new OutPoint(hash, i));
......
......@@ -8,7 +8,7 @@ namespace NBitcoin.BuilderExtensions
{
public override bool CanCombineScriptSig(Network network, Script scriptPubKey, Script a, Script b)
{
return PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(network, scriptPubKey) != null;
return PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey) != null;
}
public override bool CanDeduceScriptPubKey(Network network, Script scriptSig)
......@@ -18,31 +18,31 @@ namespace NBitcoin.BuilderExtensions
public override bool CanEstimateScriptSigSize(Network network, Script scriptPubKey)
{
return PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(network, scriptPubKey) != null;
return PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey) != null;
}
public override bool CanGenerateScriptSig(Network network, Script scriptPubKey)
{
return PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(network, scriptPubKey) != null;
return PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey) != null;
}
public override Script CombineScriptSig(Network network, Script scriptPubKey, Script a, Script b)
{
var para = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(network, scriptPubKey);
PayToMultiSigTemplateParameters para = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);
// Combine all the signatures we've got:
var aSigs = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(network, a);
TransactionSignature[] aSigs = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(network, a);
if(aSigs == null)
return b;
var bSigs = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(network, b);
TransactionSignature[] bSigs = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(network, b);
if(bSigs == null)
return a;
int sigCount = 0;
TransactionSignature[] sigs = new TransactionSignature[para.PubKeys.Length];
var sigs = new TransactionSignature[para.PubKeys.Length];
for(int i = 0; i < para.PubKeys.Length; i++)
{
var aSig = i < aSigs.Length ? aSigs[i] : null;
var bSig = i < bSigs.Length ? bSigs[i] : null;
var sig = aSig ?? bSig;
TransactionSignature aSig = i < aSigs.Length ? aSigs[i] : null;
TransactionSignature bSig = i < bSigs.Length ? bSigs[i] : null;
TransactionSignature sig = aSig ?? bSig;
if(sig != null)
{
sigs[i] = sig;
......@@ -63,15 +63,15 @@ namespace NBitcoin.BuilderExtensions
public override int EstimateScriptSigSize(Network network, Script scriptPubKey)
{
var p2mk = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(network, scriptPubKey);
PayToMultiSigTemplateParameters p2mk = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);
return PayToMultiSigTemplate.Instance.GenerateScriptSig(Enumerable.Range(0, p2mk.SignatureCount).Select(o => DummySignature).ToArray()).Length;
}
public override Script GenerateScriptSig(Network network, Script scriptPubKey, IKeyRepository keyRepo, ISigner signer)
{
var multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(network, scriptPubKey);
TransactionSignature[] signatures = new TransactionSignature[multiSigParams.PubKeys.Length];
var keys =
PayToMultiSigTemplateParameters multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);
var signatures = new TransactionSignature[multiSigParams.PubKeys.Length];
Key[] keys =
multiSigParams
.PubKeys
.Select(p => keyRepo.FindKey(p.ScriptPubKey))
......@@ -84,7 +84,7 @@ namespace NBitcoin.BuilderExtensions
break;
if(keys[i] != null)
{
var sig = signer.Sign(keys[i]);
TransactionSignature sig = signer.Sign(keys[i]);
signatures[i] = sig;
sigCount++;
}
......
......@@ -4,29 +4,29 @@
{
public override bool CanCombineScriptSig(Network network, Script scriptPubKey, Script a, Script b)
{
return PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(network, scriptPubKey);
return PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(scriptPubKey);
}
public override bool CanDeduceScriptPubKey(Network network, Script scriptSig)
{
var para = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, scriptSig);
PayToPubkeyHashScriptSigParameters para = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, scriptSig);
return para != null && para.PublicKey != null;
}
public override bool CanEstimateScriptSigSize(Network network, Script scriptPubKey)
{
return PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(network, scriptPubKey);
return PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(scriptPubKey);
}
public override bool CanGenerateScriptSig(Network network, Script scriptPubKey)
{
return PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(network, scriptPubKey);
return PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(scriptPubKey);
}
public override Script CombineScriptSig(Network network, Script scriptPubKey, Script a, Script b)
{
var aSig = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, a);
var bSig = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, b);
PayToPubkeyHashScriptSigParameters aSig = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, a);
PayToPubkeyHashScriptSigParameters bSig = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, b);
if(aSig == null)
return b;
if(bSig == null)
......@@ -39,7 +39,7 @@
public override Script DeduceScriptPubKey(Network network, Script scriptSig)
{
var p2pkh = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, scriptSig);
PayToPubkeyHashScriptSigParameters p2pkh = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(network, scriptSig);
return p2pkh.PublicKey.Hash.ScriptPubKey;
}
......@@ -50,11 +50,11 @@
public override Script GenerateScriptSig(Network network, Script scriptPubKey, IKeyRepository keyRepo, ISigner signer)
{
var parameters = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);
var key = keyRepo.FindKey(parameters.ScriptPubKey);
KeyId parameters = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);
Key key = keyRepo.FindKey(parameters.ScriptPubKey);
if(key == null)
return null;
var sig = signer.Sign(key);
TransactionSignature sig = signer.Sign(key);
return PayToPubkeyHashTemplate.Instance.GenerateScriptSig(sig, key.PubKey);
}
}
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NBitcoin.Protocol;
namespace NBitcoin
{
public class CachedNoSqlRepository : NoSqlRepository
{
class Raw : IBitcoinSerializable
private class Raw : IBitcoinSerializable
{
public Raw()
{
}
public Raw(byte[] data)
{
var str = new VarString();
str.FromBytes(data);
_Data = str.GetString(true);
}
private byte[] _Data = new byte[0];
public byte[] Data
{
get
{
return _Data;
return this._Data;
}
}
#region IBitcoinSerializable Members
public void ReadWrite(BitcoinStream stream)
{
stream.ReadWriteAsVarString(ref _Data);
stream.ReadWriteAsVarString(ref this._Data);
}
#endregion
}
public CachedNoSqlRepository(NoSqlRepository inner)
{
_InnerRepository = inner;
}
private readonly NoSqlRepository _InnerRepository;
public NoSqlRepository InnerRepository
{
get
public CachedNoSqlRepository(NoSqlRepository inner) : base(inner.Network)
{
return _InnerRepository;
this.InnerRepository = inner;
}
}
Dictionary<string, byte[]> _Table = new Dictionary<string, byte[]>();
HashSet<string> _Removed = new HashSet<string>();
HashSet<string> _Added = new HashSet<string>();
ReaderWriterLock @lock = new ReaderWriterLock();
public NoSqlRepository InnerRepository { get; }
private Dictionary<string, byte[]> _Table = new Dictionary<string, byte[]>();
private HashSet<string> _Removed = new HashSet<string>();
private HashSet<string> _Added = new HashSet<string>();
private ReaderWriterLock @lock = new ReaderWriterLock();
public override async Task PutBatch(IEnumerable<Tuple<string, IBitcoinSerializable>> values)
{
await base.PutBatch(values).ConfigureAwait(false);
await _InnerRepository.PutBatch(values).ConfigureAwait(false);
await this.InnerRepository.PutBatch(values).ConfigureAwait(false);
}
protected override Task PutBytesBatch(IEnumerable<Tuple<string, byte[]>> enumerable)
{
using(@lock.LockWrite())
using (this.@lock.LockWrite())
{
foreach(var data in enumerable)
foreach (Tuple<string, byte[]> data in enumerable)
{
if(data.Item2 == null)
if (data.Item2 == null)
{
_Table.Remove(data.Item1);
_Removed.Add(data.Item1);
_Added.Remove(data.Item1);
this._Table.Remove(data.Item1);
this._Removed.Add(data.Item1);
this._Added.Remove(data.Item1);
}
else
{
_Table.AddOrReplace(data.Item1, data.Item2);
_Removed.Remove(data.Item1);
_Added.Add(data.Item1);
this._Table.AddOrReplace(data.Item1, data.Item2);
this._Removed.Remove(data.Item1);
this._Added.Add(data.Item1);
}
}
}
......@@ -88,37 +77,23 @@ namespace NBitcoin
{
byte[] result = null;
bool found;
using(@lock.LockRead())
using (this.@lock.LockRead())
{
found = _Table.TryGetValue(key, out result);
found = this._Table.TryGetValue(key, out result);
}
if(!found)
if (!found)
{
var raw = await InnerRepository.GetAsync<Raw>(key).ConfigureAwait(false);
if(raw != null)
Raw raw = await this.InnerRepository.GetAsync<Raw>(key).ConfigureAwait(false);
if (raw != null)
{
result = raw.Data;
using(@lock.LockWrite())
using (this.@lock.LockWrite())
{
_Table.AddOrReplace(key, raw.Data);
this._Table.AddOrReplace(key, raw.Data);
}
}
}
return result;
}
public void Flush()
{
using(@lock.LockWrite())
{
InnerRepository
.PutBatch(_Removed.Select(k => Tuple.Create<string, IBitcoinSerializable>(k, null))
.Concat(_Added.Select(k => Tuple.Create<string, IBitcoinSerializable>(k, new Raw(_Table[k])))))
.GetAwaiter().GetResult();
_Removed.Clear();
_Added.Clear();
_Table.Clear();
}
}
}
}
\ No newline at end of file
This diff is collapsed.
using System;
namespace NBitcoin
{
/// <summary>
/// A default object factory to create instances that is not block, block header or transaction.
/// </summary>
public sealed class DefaultConsensusFactory : ConsensusFactory
{
/// <inheritdoc/>
public override T TryCreateNew<T>()
{
if (this.IsBlock<T>() || this.IsBlockHeader<T>() || this.IsTransaction<T>())
throw new Exception(string.Format("{0} cannot be created by this consensus factory, please use the appropriate one.", typeof(T).Name));
return default(T);
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
using NBitcoin.BouncyCastle.Math;
using NBitcoin.DataEncoders;
namespace NBitcoin.Networks
{
class DeStreamRegTest
public class DeStreamRegTest : Network
{
public DeStreamRegTest()
{
// TODO: move this to Networks
var messageStart = new byte[4];
messageStart[0] = 0xcd;
messageStart[1] = 0xf2;
messageStart[2] = 0xc0;
messageStart[3] = 0xef;
var magic = BitConverter.ToUInt32(messageStart, 0); // 0xefc0f2cd
this.Name = "DeStreamRegTest";
this.RootFolderName = DeStreamRootFolderName;
this.DefaultConfigFilename = DeStreamDefaultConfigFilename;
this.Magic = magic;
this.DefaultPort = 18444;
this.RPCPort = 18442;
this.MaxTimeOffsetSeconds = StratisMaxTimeOffsetSeconds;
this.MaxTipAge = StratisDefaultMaxTipAgeInSeconds;
this.Consensus.SubsidyHalvingInterval = 210000;
this.Consensus.MajorityEnforceBlockUpgrade = 750;
this.Consensus.MajorityRejectBlockOutdated = 950;
this.Consensus.MajorityWindow = 1000;
this.Consensus.BuriedDeployments[BuriedDeployments.BIP34] = 0;
this.Consensus.BuriedDeployments[BuriedDeployments.BIP65] = 0;
this.Consensus.BuriedDeployments[BuriedDeployments.BIP66] = 0;
this.Consensus.BIP34Hash = new uint256("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8");
this.Consensus.PowLimit = new Target(uint256.Parse("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
this.Consensus.PowTargetTimespan = TimeSpan.FromSeconds(14 * 24 * 60 * 60); // two weeks
this.Consensus.PowTargetSpacing = TimeSpan.FromSeconds(10 * 60);
this.Consensus.PowAllowMinDifficultyBlocks = true;
this.Consensus.PowNoRetargeting = true;
this.Consensus.RuleChangeActivationThreshold = 1916; // 95% of 2016
this.Consensus.MinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
this.Consensus.LastPOWBlock = 12500;
this.Consensus.IsProofOfStake = true;
this.Consensus.ConsensusFactory = new PosConsensusFactory() { Consensus = this.Consensus };
this.Consensus.ProofOfStakeLimit = new BigInteger(uint256.Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false));
this.Consensus.ProofOfStakeLimitV2 = new BigInteger(uint256.Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false));
this.Consensus.CoinType = 105;
this.Consensus.DefaultAssumeValid = null; // turn off assumevalid for regtest.
Block genesis = CreateStratisGenesisBlock(this.Consensus.ConsensusFactory, 1470467000, 1831645, 0x1e0fffff, 1, Money.Zero);
genesis.Header.Time = 1494909211;
genesis.Header.Nonce = 2433759;
genesis.Header.Bits = this.Consensus.PowLimit;
this.Genesis = genesis;
this.Consensus.HashGenesisBlock = genesis.GetHash();
Assert(this.Consensus.HashGenesisBlock == uint256.Parse("0x93925104d664314f581bc7ecb7b4bad07bcfabd1cfce4256dbd2faddcf53bd1f"));
this.Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (65) };
this.Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (196) };
this.Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (65 + 128) };
this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_NO_EC] = new byte[] { 0x01, 0x42 };
this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_EC] = new byte[] { 0x01, 0x43 };
this.Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x88), (0xB2), (0x1E) };
this.Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x88), (0xAD), (0xE4) };
this.Base58Prefixes[(int)Base58Type.PASSPHRASE_CODE] = new byte[] { 0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2 };
this.Base58Prefixes[(int)Base58Type.CONFIRMATION_CODE] = new byte[] { 0x64, 0x3B, 0xF6, 0xA8, 0x9A };
this.Base58Prefixes[(int)Base58Type.STEALTH_ADDRESS] = new byte[] { 0x2a };
this.Base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 23 };
this.Base58Prefixes[(int)Base58Type.COLORED_ADDRESS] = new byte[] { 0x13 };
var encoder = new Bech32Encoder("bc");
this.Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder;
this.Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder;
}
}
}
......@@ -34,7 +34,7 @@ namespace NBitcoin.Networks
this.FallbackFee = 60000;
this.MinRelayTxFee = 10000;
this..Consensus.SubsidyHalvingInterval = 210000;
this.Consensus.SubsidyHalvingInterval = 210000;
this.Consensus.MajorityEnforceBlockUpgrade = 750;
this.Consensus.MajorityRejectBlockOutdated = 950;
this.Consensus.MajorityWindow = 1000;
......@@ -51,7 +51,7 @@ namespace NBitcoin.Networks
this.Consensus.MinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
this.Consensus.LastPOWBlock = 12500;
this.Consensus.IsProofOfStake = true;
this.Consensus.ConsensusFactory = new PosConsensusFactory() { Consensus = network.Consensus };
this.Consensus.ConsensusFactory = new PosConsensusFactory() { Consensus = this.Consensus };
this.Consensus.ProofOfStakeLimit = new BigInteger(uint256.Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false));
this.Consensus.ProofOfStakeLimitV2 = new BigInteger(uint256.Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false));
this.Consensus.CoinType = 105;
......
......@@ -7,16 +7,16 @@ namespace NBitcoin
{
public abstract class NoSqlRepository
{
private readonly Network network;
public readonly Network Network;
protected NoSqlRepository(Network network = null)
protected NoSqlRepository(Network network)
{
this.network = network ?? Network.Main;
this.Network = network;
}
public Task PutAsync(string key, IBitcoinSerializable obj)
{
return PutBytes(key, obj == null ? null : obj.ToBytes(network: this.network));
return PutBytes(key, obj == null ? null : obj.ToBytes(this.Network.Consensus.ConsensusFactory));
}
public void Put(string key, IBitcoinSerializable obj)
......@@ -26,12 +26,13 @@ namespace NBitcoin
public async Task<T> GetAsync<T>(string key) where T : IBitcoinSerializable, new()
{
var data = await GetBytes(key).ConfigureAwait(false);
if(data == null)
byte[] data = await GetBytes(key).ConfigureAwait(false);
if (data == null)
return default(T);
if (!this.network.Consensus.ConsensusFactory.TryCreateNew<T>(out T obj))
T obj = this.Network.Consensus.ConsensusFactory.TryCreateNew<T>();
if (obj == null)
obj = Activator.CreateInstance<T>();
obj.ReadWrite(data, network: this.network);
obj.ReadWrite(data, consensusFactory: this.Network.Consensus.ConsensusFactory);
return obj;
}
......
#if !NOHTTPCLIENT
using System;
using System;
using System.Net.Http;
using System.Threading.Tasks;
......@@ -7,14 +6,8 @@ namespace NBitcoin
{
public class QBitNinjaTransactionRepository : ITransactionRepository
{
private readonly Uri _BaseUri;
public Uri BaseUri
{
get
{
return _BaseUri;
}
}
public readonly Uri BaseUri;
private readonly Network network;
/// <summary>
/// Use qbitninja public servers
......@@ -22,38 +15,35 @@ namespace NBitcoin
/// <param name="network"></param>
public QBitNinjaTransactionRepository(Network network)
{
if(network == null)
throw new ArgumentNullException("network");
_BaseUri = new Uri("http://" + (network == Network.Main ? "" : "t") + "api.qbit.ninja/");
this.network = network ?? throw new ArgumentNullException("network");
this.BaseUri = new Uri("http://" + (network == Network.Main ? "" : "t") + "api.qbit.ninja/");
}
public QBitNinjaTransactionRepository(Uri baseUri)
: this(baseUri.AbsoluteUri)
{
}
public QBitNinjaTransactionRepository(string baseUri)
{
if(!baseUri.EndsWith("/"))
baseUri += "/";
_BaseUri = new Uri(baseUri, UriKind.Absolute);
}
#region ITransactionRepository Members
this.BaseUri = new Uri(baseUri, UriKind.Absolute);
}
public async Task<Transaction> GetAsync(uint256 txId)
{
using(HttpClient client = new HttpClient())
using(var client = new HttpClient())
{
var tx = await client.GetAsync(BaseUri.AbsoluteUri + "transactions/" + txId + "?format=raw").ConfigureAwait(false);
HttpResponseMessage tx = await client.GetAsync(this.BaseUri.AbsoluteUri + "transactions/" + txId + "?format=raw").ConfigureAwait(false);
if(tx.StatusCode == System.Net.HttpStatusCode.NotFound)
return null;
tx.EnsureSuccessStatusCode();
var bytes = await tx.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
return new Transaction(bytes);
byte[] bytes = await tx.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
return this.network.CreateTransaction(bytes);
}
}
......@@ -61,8 +51,5 @@ namespace NBitcoin
{
return Task.FromResult(false);
}
#endregion
}
}
\ No newline at end of file
#endif
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
namespace NBitcoin.RPC
{
public class AddressGrouping
{
public AddressGrouping()
{
this.ChangeAddresses = new List<ChangeAddress>();
}
public BitcoinAddress PublicAddress { get; set; }
public Money Amount { get; set; }
public string Account { get; set; }
public List<ChangeAddress> ChangeAddresses { get; set; }
}
}
......@@ -5,8 +5,12 @@ using Newtonsoft.Json.Linq;
namespace NBitcoin.RPC
{
class BlockExplorerFormatter : RawFormatter
internal class BlockExplorerFormatter : RawFormatter
{
internal BlockExplorerFormatter(Network network) : base(network)
{
}
protected override void BuildTransaction(JObject json, Transaction tx)
{
tx.Version = (uint)json.GetValue("ver");
......@@ -14,7 +18,7 @@ namespace NBitcoin.RPC
var vin = (JArray)json.GetValue("in");
int vinCount = (int)json.GetValue("vin_sz");
for(int i = 0; i < vinCount; i++)
for (int i = 0; i < vinCount; i++)
{
var jsonIn = (JObject)vin[i];
var txin = new TxIn();
......@@ -25,19 +29,19 @@ namespace NBitcoin.RPC
txin.PrevOut.N = (uint)prevout.GetValue("n");
var script = (string)jsonIn.GetValue("scriptSig");
if(script != null)
string script = (string)jsonIn.GetValue("scriptSig");
if (script != null)
{
txin.ScriptSig = new Script(script);
}
else
{
var coinbase = (string)jsonIn.GetValue("coinbase");
string coinbase = (string)jsonIn.GetValue("coinbase");
txin.ScriptSig = new Script(Encoders.Hex.DecodeData(coinbase));
}
var seq = jsonIn.GetValue("sequence");
if(seq != null)
JToken seq = jsonIn.GetValue("sequence");
if (seq != null)
{
txin.Sequence = (uint)seq;
}
......@@ -45,10 +49,10 @@ namespace NBitcoin.RPC
var vout = (JArray)json.GetValue("out");
int voutCount = (int)json.GetValue("vout_sz");
for(int i = 0; i < voutCount; i++)
for (int i = 0; i < voutCount; i++)
{
var jsonOut = (JObject)vout[i];
var txout = new NBitcoin.TxOut();
var txout = new TxOut();
tx.Outputs.Add(txout);
txout.Value = Money.Parse((string)jsonOut.GetValue("value"));
......@@ -70,9 +74,9 @@ namespace NBitcoin.RPC
writer.WritePropertyName("in");
writer.WriteStartArray();
foreach(var input in tx.Inputs.AsIndexedInputs())
foreach (IndexedTxIn input in tx.Inputs.AsIndexedInputs())
{
var txin = input.TxIn;
TxIn txin = input.TxIn;
writer.WriteStartObject();
writer.WritePropertyName("prev_out");
writer.WriteStartObject();
......@@ -80,7 +84,7 @@ namespace NBitcoin.RPC
WritePropertyValue(writer, "n", txin.PrevOut.N);
writer.WriteEndObject();
if(txin.PrevOut.Hash == uint256.Zero)
if (txin.PrevOut.Hash == uint256.Zero)
{
WritePropertyValue(writer, "coinbase", Encoders.Hex.EncodeData(txin.ScriptSig.ToBytes()));
}
......@@ -88,11 +92,11 @@ namespace NBitcoin.RPC
{
WritePropertyValue(writer, "scriptSig", txin.ScriptSig.ToString());
}
if(input.WitScript != WitScript.Empty)
if (input.WitScript != WitScript.Empty)
{
WritePropertyValue(writer, "witness", input.WitScript.ToString());
}
if(txin.Sequence != uint.MaxValue)
if (txin.Sequence != uint.MaxValue)
{
WritePropertyValue(writer, "sequence", (uint)txin.Sequence);
}
......@@ -102,7 +106,7 @@ namespace NBitcoin.RPC
writer.WritePropertyName("out");
writer.WriteStartArray();
foreach(var txout in tx.Outputs)
foreach (TxOut txout in tx.Outputs)
{
writer.WriteStartObject();
WritePropertyValue(writer, "value", txout.Value.ToString(false, false));
......
using System;
using System.Collections.Generic;
using System.Text;
namespace NBitcoin.RPC
{
public class ChangeAddress
{
public Money Amount { get; set; }
public BitcoinAddress Address { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace NBitcoin.RPC
{
public class RPCAccount
{
public Money Amount { get; set; }
public string AccountName { get; set; }
}
}
......@@ -8,31 +8,6 @@ using Newtonsoft.Json.Linq;
namespace NBitcoin.RPC
{
public class RPCAccount
{
public Money Amount { get; set; }
public string AccountName { get; set; }
}
public class ChangeAddress
{
public Money Amount { get; set; }
public BitcoinAddress Address { get; set; }
}
public class AddressGrouping
{
public AddressGrouping()
{
this.ChangeAddresses = new List<ChangeAddress>();
}
public BitcoinAddress PublicAddress { get; set; }
public Money Amount { get; set; }
public string Account { get; set; }
public List<ChangeAddress> ChangeAddresses { get; set; }
}
/*
Category Name Implemented
------------------ --------------------------- -----------------------
......@@ -214,8 +189,8 @@ namespace NBitcoin.RPC
if (options.SubtractFeeFromOutputs != null)
{
JArray array = new JArray();
foreach(var v in options.SubtractFeeFromOutputs)
var array = new JArray();
foreach (int v in options.SubtractFeeFromOutputs)
{
array.Add(new JValue(v));
}
......@@ -232,7 +207,7 @@ namespace NBitcoin.RPC
var r = (JObject)response.Result;
return new FundRawTransactionResponse()
{
Transaction = new Transaction(r["hex"].Value<string>()),
Transaction = this.network.CreateTransaction(r["hex"].Value<string>()),
Fee = Money.Coins(r["fee"].Value<decimal>()),
ChangePos = r["changepos"].Value<int>()
};
......@@ -246,7 +221,7 @@ namespace NBitcoin.RPC
return tx.ToHex();
// if there is, do this ACK so that NBitcoin does not change the version number
return Encoders.Hex.EncodeData(tx.ToBytes(NBitcoin.Protocol.ProtocolVersion.WITNESS_VERSION - 1));
return Encoders.Hex.EncodeData(tx.ToBytes(version: NBitcoin.Protocol.ProtocolVersion.WITNESS_VERSION - 1));
}
// getreceivedbyaddress
......@@ -609,7 +584,7 @@ namespace NBitcoin.RPC
public async Task<Transaction> SignRawTransactionAsync(Transaction tx)
{
RPCResponse result = await SendCommandAsync(RPCOperations.signrawtransaction, tx.ToHex()).ConfigureAwait(false);
return new Transaction(result.Result["hex"].Value<string>());
return this.network.CreateTransaction(result.Result["hex"].Value<string>());
}
}
}
......
......@@ -6,13 +6,13 @@ using Newtonsoft.Json.Linq;
namespace NBitcoin.RPC
{
abstract class RawFormatter
internal abstract class RawFormatter
{
public Network Network { get; set; }
protected RawFormatter()
protected RawFormatter(Network network)
{
this.Network = Network.Main;
this.Network = network;
}
protected abstract void BuildTransaction(JObject json, Transaction tx);
......@@ -34,7 +34,7 @@ namespace NBitcoin.RPC
public Transaction Parse(JObject obj)
{
Transaction tx = new Transaction();
var tx = new Transaction();
BuildTransaction(obj, tx);
return tx;
}
......
......@@ -27,44 +27,17 @@ namespace NBitcoin.RPC
private readonly Uri address;
private readonly Network network;
/// <summary>
/// Gets the <see cref="Network"/> instance for the client.
/// </summary>
public Network Network
{
get
{
return network;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="RestClient"/> class.
/// </summary>
/// <param name="address">The rest API endpoint</param>
/// <exception cref="System.ArgumentNullException">Null rest API endpoint</exception>
/// <exception cref="System.ArgumentException">Invalid value for RestResponseFormat</exception>
public RestClient(Uri address)
: this(address, Network.Main)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RestClient"/> class.
/// </summary>
/// <param name="address">The rest API endpoint</param>
/// <param name="network">The network to operate with</param>
/// <exception cref="System.ArgumentNullException">Null rest API endpoint</exception>
/// <exception cref="System.ArgumentException">Invalid value for RestResponseFormat</exception>
/// <exception cref="ArgumentNullException">Null rest API endpoint</exception>
/// <exception cref="ArgumentException">Invalid value for RestResponseFormat</exception>
public RestClient(Uri address, Network network)
{
if (address == null)
throw new ArgumentNullException("address");
if (network == null)
throw new ArgumentNullException("network");
this.address = address;
this.network = network;
this.address = address ?? throw new ArgumentNullException(nameof(address));
this.network = network ?? throw new ArgumentNullException(nameof(network));
}
/// <summary>
......@@ -72,14 +45,14 @@ namespace NBitcoin.RPC
/// </summary>
/// <param name="blockId">The block identifier.</param>
/// <returns>Given a block hash (id) returns the requested block object.</returns>
/// <exception cref="System.ArgumentNullException">blockId cannot be null.</exception>
/// <exception cref="ArgumentNullException">blockId cannot be null.</exception>
public async Task<Block> GetBlockAsync(uint256 blockId)
{
if (blockId == null)
throw new ArgumentNullException("blockId");
byte[] result = await SendRequestAsync("block", RestResponseFormat.Bin, blockId.ToString()).ConfigureAwait(false);
return new Block(result);
return Block.Load(result, this.network);
}
/// <summary>
......@@ -87,7 +60,7 @@ namespace NBitcoin.RPC
/// </summary>
/// <param name="blockId">The block identifier.</param>
/// <returns>Given a block hash (id) returns the requested block object.</returns>
/// <exception cref="System.ArgumentNullException">blockId cannot be null.</exception>
/// <exception cref="ArgumentNullException">blockId cannot be null.</exception>
public Block GetBlock(uint256 blockId)
{
return GetBlockAsync(blockId).GetAwaiter().GetResult();
......@@ -105,7 +78,7 @@ namespace NBitcoin.RPC
throw new ArgumentNullException("txId");
byte[] result = await SendRequestAsync("tx", RestResponseFormat.Bin, txId.ToString()).ConfigureAwait(false);
return new Transaction(result);
return this.network.CreateTransaction(result);
}
/// <summary>
......@@ -150,8 +123,8 @@ namespace NBitcoin.RPC
/// <param name="blockId">The initial block identifier.</param>
/// <param name="count">how many headers to get.</param>
/// <returns>Given a block hash (blockId) returns as much block headers as specified.</returns>
/// <exception cref="System.ArgumentNullException">blockId cannot be null</exception>
/// <exception cref="System.ArgumentOutOfRangeException">count must be greater or equal to one.</exception>
/// <exception cref="ArgumentNullException">blockId cannot be null</exception>
/// <exception cref="ArgumentOutOfRangeException">count must be greater or equal to one.</exception>
public IEnumerable<BlockHeader> GetBlockHeaders(uint256 blockId, int count)
{
return GetBlockHeadersAsync(blockId, count).GetAwaiter().GetResult();
......@@ -164,7 +137,7 @@ namespace NBitcoin.RPC
public async Task<ChainInfo> GetChainInfoAsync()
{
byte[] result = await SendRequestAsync("chaininfo", RestResponseFormat.Json).ConfigureAwait(false);
var o = JObject.Parse(Encoding.UTF8.GetString(result, 0, result.Length));
JObject o = JObject.Parse(Encoding.UTF8.GetString(result, 0, result.Length));
return new ChainInfo
{
......@@ -185,7 +158,7 @@ namespace NBitcoin.RPC
/// <param name="outPoints">The out points identifiers (TxIn-N).</param>
/// <param name="checkMempool">if set to <c>true</c> [check mempool].</param>
/// <returns>The unspent transaction outputs (UTXO) for the given outPoints.</returns>
/// <exception cref="System.ArgumentNullException">outPoints cannot be null.</exception>
/// <exception cref="ArgumentNullException">outPoints cannot be null.</exception>
public async Task<UTxOutputs> GetUnspentOutputsAsync(IEnumerable<OutPoint> outPoints, bool checkMempool)
{
if (outPoints == null)
......@@ -216,11 +189,11 @@ namespace NBitcoin.RPC
byte[] result = await SendRequestAsync($"gettxout/{txid.ToString()}/{vout.ToString() + (includeMemPool ? "/includemempool" : "")}",
RestResponseFormat.Json).ConfigureAwait(false);
var responseString = Encoding.UTF8.GetString(result, 0, result.Length);
string responseString = Encoding.UTF8.GetString(result, 0, result.Length);
if (string.IsNullOrEmpty(responseString))
return null;
var objectResult = JObject.Parse(responseString);
JObject objectResult = JObject.Parse(responseString);
return new UnspentTransaction(objectResult);
}
......@@ -232,23 +205,22 @@ namespace NBitcoin.RPC
using (WebResponse response = await GetWebResponseAsync(request).ConfigureAwait(false))
{
Stream stream = response.GetResponseStream();
var bytesToRead = (int)response.ContentLength;
int bytesToRead = (int)response.ContentLength;
byte[] buffer = await stream.ReadBytesAsync(bytesToRead).ConfigureAwait(false);
return buffer;
}
}
#region Private methods
private WebRequest BuildHttpRequest(string resource, RestResponseFormat format, params string[] parms)
{
var hasParams = parms != null && parms.Length > 0;
bool hasParams = parms != null && parms.Length > 0;
var uriBuilder = new UriBuilder(this.address);
uriBuilder.Path = "rest/" + resource + (hasParams ? "/" : "") + string.Join("/", parms) + "." + format.ToString().ToLowerInvariant();
HttpWebRequest request = WebRequest.CreateHttp(uriBuilder.Uri);
request.Method = "GET";
#if !(PORTABLE || NETCORE)
#if !NETCORE
request.KeepAlive = false;
#endif
return request;
......@@ -263,10 +235,8 @@ namespace NBitcoin.RPC
{
response = await request.GetResponseAsync().ConfigureAwait(false);
}
catch(WebException ex)
catch (WebException ex)
{
// "WebException status: {0}", ex.Status);
// Even if the request "failed" we need to continue reading the response from the router
response = ex.Response as HttpWebResponse;
......@@ -279,14 +249,13 @@ namespace NBitcoin.RPC
if (exception != null)
{
Stream stream = response.GetResponseStream();
var bytesToRead = (int)response.ContentLength;
int bytesToRead = (int)response.ContentLength;
byte[] buffer = await stream.ReadBytesAsync(bytesToRead).ConfigureAwait(false);
response.Dispose();
throw new RestApiException(Encoding.UTF8.GetString(buffer, 0, buffer.Length - 2), exception);
}
return response;
}
#endregion
}
public class RestApiException : Exception
......
......@@ -8,13 +8,10 @@ using Newtonsoft.Json.Linq;
namespace NBitcoin.RPC
{
class SatoshiFormatter : RawFormatter
internal class SatoshiFormatter : RawFormatter
{
private readonly Network network;
public SatoshiFormatter(Network network)
public SatoshiFormatter(Network network) : base(network)
{
this.network = network;
}
protected override void BuildTransaction(JObject json, Transaction tx)
......@@ -23,14 +20,14 @@ namespace NBitcoin.RPC
tx.LockTime = (uint)json.GetValue("locktime");
var vin = (JArray)json.GetValue("vin");
for(int i = 0; i < vin.Count; i++)
for (int i = 0; i < vin.Count; i++)
{
var jsonIn = (JObject)vin[i];
var txin = new TxIn();
tx.Inputs.Add(txin);
var script = (JObject)jsonIn.GetValue("scriptSig");
if(script != null)
if (script != null)
{
txin.ScriptSig = new Script(Encoders.Hex.DecodeData((string)script.GetValue("hex")));
txin.PrevOut.Hash = uint256.Parse((string)jsonIn.GetValue("txid"));
......@@ -38,7 +35,7 @@ namespace NBitcoin.RPC
}
else
{
var coinbase = (string)jsonIn.GetValue("coinbase");
string coinbase = (string)jsonIn.GetValue("coinbase");
txin.ScriptSig = new Script(Encoders.Hex.DecodeData(coinbase));
}
......@@ -47,14 +44,14 @@ namespace NBitcoin.RPC
}
var vout = (JArray)json.GetValue("vout");
for(int i = 0; i < vout.Count; i++)
for (int i = 0; i < vout.Count; i++)
{
var jsonOut = (JObject)vout[i];
var txout = new TxOut();
tx.Outputs.Add(txout);
var btc = (decimal)jsonOut.GetValue("value");
var satoshis = btc * Money.COIN;
decimal btc = (decimal)jsonOut.GetValue("value");
decimal satoshis = btc * Money.COIN;
txout.Value = new Money((long)(satoshis));
var script = (JObject)jsonOut.GetValue("scriptPubKey");
......@@ -70,11 +67,11 @@ namespace NBitcoin.RPC
writer.WritePropertyName("vin");
writer.WriteStartArray();
foreach(var txin in tx.Inputs)
foreach (TxIn txin in tx.Inputs)
{
writer.WriteStartObject();
if(txin.PrevOut.Hash == uint256.Zero)
if (txin.PrevOut.Hash == uint256.Zero)
{
WritePropertyValue(writer, "coinbase", Encoders.Hex.EncodeData(txin.ScriptSig.ToBytes()));
}
......@@ -99,7 +96,7 @@ namespace NBitcoin.RPC
writer.WriteStartArray();
int i = 0;
foreach(var txout in tx.Outputs)
foreach (TxOut txout in tx.Outputs)
{
writer.WriteStartObject();
writer.WritePropertyName("value");
......@@ -112,28 +109,28 @@ namespace NBitcoin.RPC
WritePropertyValue(writer, "asm", txout.ScriptPubKey.ToString());
WritePropertyValue(writer, "hex", Encoders.Hex.EncodeData(txout.ScriptPubKey.ToBytes()));
var destinations = new List<TxDestination>() { txout.ScriptPubKey.GetDestination(this.network) };
if(destinations[0] == null)
var destinations = new List<TxDestination>() { txout.ScriptPubKey.GetDestination(this.Network) };
if (destinations[0] == null)
{
destinations = txout.ScriptPubKey.GetDestinationPublicKeys(this.network)
destinations = txout.ScriptPubKey.GetDestinationPublicKeys(this.Network)
.Select(p => p.Hash)
.ToList<TxDestination>();
}
if(destinations.Count == 1)
if (destinations.Count == 1)
{
WritePropertyValue(writer, "reqSigs", 1);
WritePropertyValue(writer, "type", GetScriptType(txout.ScriptPubKey.FindTemplate(this.network)));
WritePropertyValue(writer, "type", GetScriptType(txout.ScriptPubKey.FindTemplate(this.Network)));
writer.WritePropertyName("addresses");
writer.WriteStartArray();
writer.WriteValue(destinations[0].GetAddress(Network).ToString());
writer.WriteValue(destinations[0].GetAddress(this.Network).ToString());
writer.WriteEndArray();
}
else
{
var multi = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(this.network, txout.ScriptPubKey);
PayToMultiSigTemplateParameters multi = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(txout.ScriptPubKey);
if (multi != null)
WritePropertyValue(writer, "reqSigs", multi.SignatureCount);
WritePropertyValue(writer, "type", GetScriptType(txout.ScriptPubKey.FindTemplate(this.network)));
WritePropertyValue(writer, "type", GetScriptType(txout.ScriptPubKey.FindTemplate(this.Network)));
if (multi != null)
{
writer.WritePropertyName("addresses");
......@@ -155,20 +152,20 @@ namespace NBitcoin.RPC
private string ValueFromAmount(Money money)
{
var satoshis = (decimal)money.Satoshi;
var btc = satoshis / Money.COIN;
decimal satoshis = (decimal)money.Satoshi;
decimal btc = satoshis / Money.COIN;
//return btc.ToString("0.###E+00", CultureInfo.InvariantCulture);
var result = ((double)btc).ToString(CultureInfo.InvariantCulture);
if(!result.ToCharArray().Contains('.'))
string result = ((double)btc).ToString(CultureInfo.InvariantCulture);
if (!result.ToCharArray().Contains('.'))
result = result + ".0";
return result;
}
private string GetScriptType(ScriptTemplate template)
{
if(template == null)
if (template == null)
return "nonstandard";
switch(template.Type)
switch (template.Type)
{
case TxOutType.TX_PUBKEY:
return "pubkey";
......
This diff is collapsed.
......@@ -4,10 +4,9 @@ using NBitcoin.Policy;
namespace NBitcoin
{
public static class StandardScripts
{
static readonly ScriptTemplate[] _StandardTemplates = new ScriptTemplate[]
private static readonly ScriptTemplate[] _StandardTemplates = new ScriptTemplate[]
{
PayToPubkeyHashTemplate.Instance,
PayToPubkeyTemplate.Instance,
......@@ -17,10 +16,8 @@ namespace NBitcoin
PayToWitTemplate.Instance
};
public static bool IsStandardTransaction(Transaction tx, Network network = null)
public static bool IsStandardTransaction(Transaction tx, Network network)
{
network = network ?? Network.Main;
return new StandardTransactionPolicy(network).Check(tx, null).Length == 0;
}
......@@ -29,25 +26,25 @@ namespace NBitcoin
return tx.Outputs.All(vout => IsStandardScriptPubKey(network, vout.ScriptPubKey));
}
public static ScriptTemplate GetTemplateFromScriptPubKey(Network network, Script script)
public static ScriptTemplate GetTemplateFromScriptPubKey(Script script)
{
return _StandardTemplates.FirstOrDefault(t => t.CheckScriptPubKey(network, script));
return _StandardTemplates.FirstOrDefault(t => t.CheckScriptPubKey(script));
}
public static bool IsStandardScriptPubKey(Network network, Script scriptPubKey)
{
return _StandardTemplates.Any(template => template.CheckScriptPubKey(network, scriptPubKey));
return _StandardTemplates.Any(template => template.CheckScriptPubKey(scriptPubKey));
}
private static bool IsStandardScriptSig(Network network, Script scriptSig, Script scriptPubKey)
{
var template = GetTemplateFromScriptPubKey(network, scriptPubKey);
ScriptTemplate template = GetTemplateFromScriptPubKey(scriptPubKey);
if(template == null)
return false;
return template.CheckScriptSig(network, scriptSig, scriptPubKey);
}
//
// Check transaction inputs, and make sure any
// pay-to-script-hash transactions are evaluating IsStandard scripts
//
......@@ -57,13 +54,12 @@ namespace NBitcoin
// script can be anything; an attacker could use a very
// expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
//
public static bool AreInputsStandard(Network network, Transaction tx, CoinsView coinsView)
{
if(tx.IsCoinBase)
return true; // Coinbases don't use vin normally
foreach(var input in tx.Inputs)
foreach(TxIn input in tx.Inputs)
{
TxOut prev = coinsView.GetOutputFor(input);
if(prev == null)
......
......@@ -16,9 +16,10 @@ namespace NBitcoin.Stealth
}
throw new ArgumentException("No nonce can satisfy the given bitfield, use another ephemKey");
}
public static StealthMetadata TryParse(Script metadata)
{
StealthMetadata result = new StealthMetadata();
var result = new StealthMetadata();
try
{
if(!Fill(result, metadata))
......@@ -30,9 +31,11 @@ namespace NBitcoin.Stealth
}
return result;
}
private StealthMetadata()
{
}
public StealthMetadata(Script metadata)
{
if(!Fill(this, metadata))
......@@ -43,19 +46,20 @@ namespace NBitcoin.Stealth
{
var data = new MemoryStream();
data.WriteByte(6);
var b = Utils.ToBytes(nonce, true);
byte[] b = Utils.ToBytes(nonce, true);
data.Write(b, 0, b.Length);
data.Write(ephemKey.PubKey.Compress().ToBytes(), 0, 33);
Fill(this, new Script(OpcodeType.OP_RETURN, Op.GetPushOp(data.ToArray())));
}
static TxNullDataTemplate _Template = new TxNullDataTemplate(1024 * 4);
private static TxNullDataTemplate _Template = new TxNullDataTemplate(1024 * 4);
private static bool Fill(StealthMetadata output, Script metadata)
{
var datas = _Template.ExtractScriptPubKeyParameters(Network.Main, metadata);
byte[][] datas = _Template.ExtractScriptPubKeyParameters(metadata);
if(datas == null)
return false;
foreach(var data in datas)
foreach(byte[] data in datas)
{
if(Fill(output, metadata, data))
return true;
......@@ -67,7 +71,7 @@ namespace NBitcoin.Stealth
{
if(data == null || data.Length != 1 + 4 + 33)
return false;
MemoryStream ms = new MemoryStream(data);
var ms = new MemoryStream(data);
output.Version = ms.ReadByte();
if(output.Version != 6)
return false;
......
......@@ -11,7 +11,7 @@ namespace NBitcoin.Stealth
{
get
{
return _Payment;
return this._Payment;
}
}
private readonly KeyId _ID;
......@@ -19,18 +19,18 @@ namespace NBitcoin.Stealth
{
get
{
return _ID;
return this._ID;
}
}
public StealthSpendKey(KeyId id, StealthPayment payment)
{
_ID = id;
_Payment = payment;
this._ID = id;
this._Payment = payment;
}
public BitcoinAddress GetAddress(Network network)
{
return new BitcoinPubKeyAddress(ID, network);
return new BitcoinPubKeyAddress(this.ID, network);
}
}
......@@ -38,13 +38,13 @@ namespace NBitcoin.Stealth
{
public StealthPayment(BitcoinStealthAddress address, Key ephemKey, StealthMetadata metadata)
{
Metadata = metadata;
ScriptPubKey = CreatePaymentScript(address.SignatureCount, address.SpendPubKeys, ephemKey, address.ScanPubKey);
this.Metadata = metadata;
this.ScriptPubKey = CreatePaymentScript(address.SignatureCount, address.SpendPubKeys, ephemKey, address.ScanPubKey);
if(address.SignatureCount > 1)
{
Redeem = ScriptPubKey;
ScriptPubKey = ScriptPubKey.Hash.ScriptPubKey;
this.Redeem = this.ScriptPubKey;
this.ScriptPubKey = this.ScriptPubKey.Hash.ScriptPubKey;
}
SetStealthKeys();
}
......@@ -71,17 +71,16 @@ namespace NBitcoin.Stealth
return CreatePaymentScript(address.SignatureCount, address.SpendPubKeys.Select(p => p.UncoverReceiver(scan, ephemKey)).ToArray());
}
public static KeyId[] ExtractKeyIDs(Script script)
{
var keyId = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(script);
KeyId keyId = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(script);
if(keyId != null)
{
return new[] { keyId };
}
else
{
var para = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(Network.Main, script);
PayToMultiSigTemplateParameters para = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(script);
if(para == null)
throw new ArgumentException("Invalid stealth spendable output script", "spendable");
return para.PubKeys.Select(k => k.Hash).ToArray();
......@@ -93,22 +92,23 @@ namespace NBitcoin.Stealth
get;
private set;
}
public BitcoinAddress[] GetAddresses(Network network)
{
return StealthKeys.Select(k => k.GetAddress(network)).ToArray();
return this.StealthKeys.Select(k => k.GetAddress(network)).ToArray();
}
public StealthPayment(Script scriptPubKey, Script redeem, StealthMetadata metadata)
{
Metadata = metadata;
ScriptPubKey = scriptPubKey;
Redeem = redeem;
this.Metadata = metadata;
this.ScriptPubKey = scriptPubKey;
this.Redeem = redeem;
SetStealthKeys();
}
private void SetStealthKeys()
{
StealthKeys = ExtractKeyIDs(Redeem ?? ScriptPubKey).Select(id => new StealthSpendKey(id, this)).ToArray();
this.StealthKeys = ExtractKeyIDs(this.Redeem ?? this.ScriptPubKey).Select(id => new StealthSpendKey(id, this)).ToArray();
}
......@@ -134,20 +134,20 @@ namespace NBitcoin.Stealth
throw new ArgumentNullException("transaction");
if(value == null)
throw new ArgumentNullException("value");
transaction.Outputs.Add(new TxOut(0, Metadata.Script));
transaction.Outputs.Add(new TxOut(value, ScriptPubKey));
transaction.Outputs.Add(new TxOut(0, this.Metadata.Script));
transaction.Outputs.Add(new TxOut(value, this.ScriptPubKey));
}
public static StealthPayment[] GetPayments(Transaction transaction, BitcoinStealthAddress address, Key scan)
{
List<StealthPayment> result = new List<StealthPayment>();
var result = new List<StealthPayment>();
for(int i = 0; i < transaction.Outputs.Count - 1; i++)
{
var metadata = StealthMetadata.TryParse(transaction.Outputs[i].ScriptPubKey);
StealthMetadata metadata = StealthMetadata.TryParse(transaction.Outputs[i].ScriptPubKey);
if(metadata != null && (address == null || address.Prefix.Match(metadata.BitField)))
{
var scriptPubKey = transaction.Outputs[i + 1].ScriptPubKey;
var scriptId = PayToScriptHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);
Script scriptPubKey = transaction.Outputs[i + 1].ScriptPubKey;
ScriptId scriptId = PayToScriptHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);
Script expectedScriptPubKey = address == null ? scriptPubKey : null;
Script redeem = null;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment