public async Task LoadNFTFromNetwork() { if (!string.IsNullOrEmpty(Utxo)) { Loading = true; if (Utxo.Contains(':')) { NFT = await NFTFactory.GetNFT("", Utxo.Split(':')[0], wait : true); } else { NFT = await NFTFactory.GetNFT("", Utxo, wait : true); } if (NFT != null) { if (nftCard != null) { nftCard.LoadNFT(NFT); } } else { NFT = new ImageNFT(""); } Loading = false; } StateHasChanged(); }
public void TestCanSpend_NegativeIndex() { // prepare utxo storage var unspentTransactions = ImmutableDictionary.CreateBuilder <UInt256, UnspentTx>(); var unspentOutputs = ImmutableDictionary.CreateBuilder <TxOutputKey, TxOutput>(); // prepare unspent output var txHash = new UInt256(0); unspentTransactions.Add(txHash, new UnspentTx(confirmedBlockHash: 0, length: 1, state: OutputState.Unspent)); unspentOutputs.Add(new TxOutputKey(txHash, UInt32.MaxValue), new TxOutput(0, ImmutableArray.Create <byte>())); // prepare utxo var chainStateStorage = new MemoryChainStateStorage(0, unspentTransactions.ToImmutable(), unspentOutputs.ToImmutable()); var utxo = new Utxo(chainStateStorage); // prepare output reference var prevTxOutput = new TxOutputKey(txHash, txOutputIndex: UInt32.MaxValue); // check if output can be spent var canSpend = utxo.CanSpend(prevTxOutput); // verify output cannot be spent Assert.IsFalse(canSpend); }
public static ChainState CreateForGenesisBlock(ChainedHeader genesisBlock) { return(new ChainState( Chain.CreateForGenesisBlock(genesisBlock), Utxo.CreateForGenesisBlock(genesisBlock.Hash) )); }
private void Init() { byte[] data = fileMan.ReadData(DbName); if (data is not null && data.Length != 0) { var stream = new FastStreamReader(data); while (true) { var utxo = new Utxo(); if (stream.TryReadByteArray(32, out byte[] hash) && utxo.TryDeserialize(stream, out _))
private void InitTestData() { this.h2utxo = null; this.h3tx = null; this.bobVerified = false; this.miners = new List <IWallet>(); this.alice = new SimpleWallet("Alice"); this.bob = new SimpleWallet("Bob"); this.nodes = new List <Node>(); this.center = new InMemoryConnectionCenter(); this.nodeNumber = 2; this.clientData = new ClientEntity { IsRunning = true }; }
public IUtxo Find(TxIn tin) { Assert.NotNull(database); bool b = database.ContainsKey(tin.TxHash); Assert.True(database.ContainsKey(tin.TxHash), "Input not found in database."); List <Utxo> ulist = database[tin.TxHash]; Utxo utxo = ulist.Find(x => x.Index == tin.Index); if (utxo is not null) { ulist.Remove(utxo); } return(utxo); }
public void TestDoubleSpend() { // prepare test kernel var kernel = new StandardKernel(new MemoryStorageModule()); // prepare block var fakeHeaders = new FakeHeaders(); var chainedHeader = new ChainedHeader(fakeHeaders.Genesis(), height: 0, totalWork: 0); // prepare an unspent transaction var txHash = new UInt256(100); var unspentTx = new UnspentTx(chainedHeader.Hash, 1, OutputState.Unspent); // mock a parent utxo containing the unspent transaction var unspentTransactions = ImmutableDictionary.Create <UInt256, UnspentTx>().Add(txHash, unspentTx); var mockParentChainStateStorage = new Mock <IChainStateStorage>(); mockParentChainStateStorage.Setup(utxo => utxo.UnspentTransactions()).Returns(unspentTransactions); var parentUtxo = new Utxo(mockParentChainStateStorage.Object); // initialize memory utxo builder storage var memoryChainStateBuilderStorage = new MemoryChainStateBuilderStorage(mockParentChainStateStorage.Object); kernel.Rebind <IChainStateBuilderStorage>().ToConstant(memoryChainStateBuilderStorage); // initialize utxo builder var chainStateBuilder = new ChainStateBuilder(null, parentUtxo, LogManager.CreateNullLogger(), kernel, null, null, null, null, null); // create an input to spend the unspent transaction var input = new TxInput(new TxOutputKey(txHash, txOutputIndex: 0), ImmutableArray.Create <byte>(), 0); var tx = new Transaction(0, ImmutableArray.Create(input), ImmutableArray.Create <TxOutput>(), 0); // spend the input chainStateBuilder.Spend(0, tx, 0, input, chainedHeader); // verify utxo storage Assert.IsFalse(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash)); // attempt to spend the input again chainStateBuilder.Spend(0, tx, 0, input, chainedHeader); // validation exception should be thrown }
public void TestCanSpend_Missing() { // prepare utxo storage var unspentTransactions = ImmutableDictionary.CreateBuilder <UInt256, UnspentTx>(); var unspentOutputs = ImmutableDictionary.CreateBuilder <TxOutputKey, TxOutput>(); // prepare utxo var chainStateStorage = new MemoryChainStateStorage(0, unspentTransactions.ToImmutable(), unspentOutputs.ToImmutable()); var utxo = new Utxo(chainStateStorage); // prepare output reference var prevTxOutput = new TxOutputKey(txHash: 0, txOutputIndex: 0); // check if output can be spent var canSpend = utxo.CanSpend(prevTxOutput); // verify output cannot be spent Assert.IsFalse(canSpend); }
//获取地址的utxo来得出地址的资产 public Dictionary <string, List <Utxo> > GetUTXOByAddress(string addr) { JObject response = nelApi.getUTXO(addr); JArray resJA = (JArray)response["result"]; Dictionary <string, List <Utxo> > _dir = new Dictionary <string, List <Utxo> >(); foreach (JObject j in resJA) { Utxo utxo = new Utxo(j["addr"].ToString(), new ThinNeo.Hash256(j["txid"].ToString()), j["asset"].ToString(), decimal.Parse(j["value"].ToString()), int.Parse(j["n"].ToString())); if (_dir.ContainsKey(j["asset"].ToString())) { _dir[j["asset"].ToString()].Add(utxo); } else { List <Utxo> l = new List <Utxo>(); l.Add(utxo); _dir[j["asset"].ToString()] = l; } } return(_dir); }
public ChainStateBuilder(ChainBuilder chain, Utxo parentUtxo, Logger logger, IKernel kernel, IBlockchainRules rules, BlockHeaderCache blockHeaderCache, BlockCache blockCache, SpentTransactionsCache spentTransactionsCache, SpentOutputsCache spentOutputsCache) { this.logger = logger; this.sha256 = new SHA256Managed(); this.rules = rules; this.blockHeaderCache = blockHeaderCache; this.blockCache = blockCache; this.spentTransactionsCache = spentTransactionsCache; this.spentOutputsCache = spentOutputsCache; this.chainStateMonitor = new ChainStateMonitor(this.logger); this.scriptValidator = new ScriptValidator(this.logger, this.rules); this.chainStateMonitor.Subscribe(this.scriptValidator); this.chain = chain; this.chainStateBuilderStorage = kernel.Get <IChainStateBuilderStorage>(new ConstructorArgument("parentUtxo", parentUtxo.Storage)); this.spentTransactions = ImmutableList.CreateBuilder <KeyValuePair <UInt256, SpentTx> >(); this.spentOutputs = ImmutableList.CreateBuilder <KeyValuePair <TxOutputKey, TxOutput> >(); this.stats = new BuilderStats(); }
public Dictionary <string, List <Utxo> > get_utxo(string txt) { MyJson.JsonNode_Object response = (MyJson.JsonNode_Object)MyJson.Parse(txt); MyJson.JsonNode_Array resJA = (MyJson.JsonNode_Array)response["result"]; Dictionary <string, List <Utxo> > _dir = new Dictionary <string, List <Utxo> >(); foreach (MyJson.JsonNode_Object j in resJA) { Utxo utxo = new Utxo(j["addr"].ToString(), new ThinNeo.Hash256(j["txid"].ToString()), j["asset"].ToString(), decimal.Parse(j["value"].ToString()), int.Parse(j["n"].ToString())); if (_dir.ContainsKey(j["asset"].ToString())) { _dir[j["asset"].ToString()].Add(utxo); } else { List <Utxo> l = new List <Utxo>(); l.Add(utxo); _dir[j["asset"].ToString()] = l; } } return(_dir); }
private void AssignEvent(Node node, int number) { node.Engine.OnNewBlockCreated += (object sender, BlockHead block) => { var engine = sender as Engine; var height = engine.BlockChain.Height; var tailBlock = engine.BlockChain.GetBlock(engine.BlockChain.Tail.Hash); Append(new BlockCreatedStatusEntity(tailBlock, $"New block created at height[{height:0000}]"), number); var me = miners[number]; // take action only on first node if (number == 0) { if (h2utxo == null) { var utxos = me.GetUtxos(engine); var utxo = utxos.First(); h2utxo = utxo; me.SendMoney(engine, utxo.Tx, utxo.Index, alice, 30, 1); Append($"send money from me to alice: 30", number); return; } if (h3tx == null) { var utxos = alice.GetUtxos(engine); var utxo = utxos.FirstOrDefault(); if (utxo != null) { alice.SyncBlockHead(engine); var verify = alice.VerifyTx(engine, utxo.Tx); Append($"verify [{utxo.Tx.Hash.ToShort()}]: {verify}", number); h3tx = alice.SendMoney(engine, utxo.Tx, utxo.Index, bob, 20); Append($"send money from alice to bob: 20", number); } return; } if (!bobVerified) { bob.SyncBlockHead(engine); var verify = bob.VerifyTx(engine, h3tx); Append($"verify [{h3tx.Hash.ToShort()}]: {verify}", number); bobVerified = verify; if (bobVerified) { // try to use used transaction which cannot pass validation and ignored me.SendMoney(engine, h2utxo.Tx, h2utxo.Index, bob, 50); } } } }; node.ConnPool.OnCommandReceived += (object sender, CommandBase e) => { var blkcmd = e as BlockCommand; Append(new CommandReceivedStatusEntity(e.CommandType, blkcmd?.Block?.Hash?.ToShort()), number); }; }
private void on_getutxo(bool timeout, WWW www) { Debug.Log(www.text); MyJson.JsonNode_Object response = (MyJson.JsonNode_Object)MyJson.Parse(www.text); if (!response.AsDict().ContainsKey("result")) { Debug.Log("交易失败"); //testtool.showNotice("交易失败"); return; } MyJson.JsonNode_Array resJA = (MyJson.JsonNode_Array)response["result"]; Dictionary <string, List <Utxo> > _dir = new Dictionary <string, List <Utxo> >(); foreach (MyJson.JsonNode_Object j in resJA) { Utxo utxo = new Utxo(j["addr"].ToString(), new ThinNeo.Hash256(j["txid"].ToString()), j["asset"].ToString(), decimal.Parse(j["value"].ToString()), int.Parse(j["n"].ToString())); if (_dir.ContainsKey(j["asset"].ToString())) { _dir[j["asset"].ToString()].Add(utxo); } else { List <Utxo> l = new List <Utxo>(); l.Add(utxo); _dir[j["asset"].ToString()] = l; } } if (_dir.ContainsKey(global.id_GAS) == false) { Debug.Log("no gas"); } ThinNeo.Transaction tran = null; { byte[] script = null; using (var sb = new ThinNeo.ScriptBuilder()) { var array = new MyJson.JsonNode_Array(); sb.EmitParamJson(array); //参数倒序入 sb.EmitParamJson(new MyJson.JsonNode_ValueString("(str)mintTokens")); //参数倒序入 ThinNeo.Hash160 shash = new ThinNeo.Hash160(global.id_sgas); sb.EmitAppCall(shash); //nep5脚本 script = sb.ToArray(); } var nep5scripthash = new ThinNeo.Hash160(global.id_sgas); var targetaddr = ThinNeo.Helper.GetAddressFromScriptHash(nep5scripthash); Debug.Log("contract address=" + targetaddr);//往合约地址转账 //生成交易 tran = Helper.makeTran(_dir[global.id_GAS], targetaddr, new ThinNeo.Hash256(global.id_GAS), m_num); tran.type = ThinNeo.TransactionType.InvocationTransaction; var idata = new ThinNeo.InvokeTransData(); tran.extdata = idata; idata.script = script; } //sign and broadcast var signdata = ThinNeo.Helper.Sign(tran.GetMessage(), roleInfo.getInstance().prikey); tran.AddWitness(signdata, roleInfo.getInstance().pubkey, roleInfo.getInstance().address); var trandata = tran.GetRawData(); var strtrandata = ThinNeo.Helper.Bytes2HexString(trandata); transaction_sgas(strtrandata); }
private void on_getutxo_1(bool timeout, WWW www) { Debug.Log(www.text); MyJson.JsonNode_Object response = (MyJson.JsonNode_Object)MyJson.Parse(www.text); if (!response.AsDict().ContainsKey("result")) { Debug.Log("交易失败"); return; } MyJson.JsonNode_Array resJA = (MyJson.JsonNode_Array)response["result"]; Dictionary <string, List <Utxo> > _dir = new Dictionary <string, List <Utxo> >(); foreach (MyJson.JsonNode_Object j in resJA) { Utxo utxo = new Utxo(j["addr"].ToString(), new ThinNeo.Hash256(j["txid"].ToString()), j["asset"].ToString(), decimal.Parse(j["value"].ToString()), int.Parse(j["n"].ToString())); if (_dir.ContainsKey(j["asset"].ToString())) { _dir[j["asset"].ToString()].Add(utxo); } else { List <Utxo> l = new List <Utxo>(); l.Add(utxo); _dir[j["asset"].ToString()] = l; } } if (_dir.ContainsKey(global.id_GAS) == false) { Debug.Log("no gas"); } ThinNeo.Transaction tran = null; { byte[] script = null; using (var sb = new ThinNeo.ScriptBuilder()) { var array = new MyJson.JsonNode_Array(); array.AddArrayValue("(addr)" + roleInfo.getInstance().address); //from array.AddArrayValue("(addr)" + global.cp_adress); //to array.AddArrayValue("(int)" + (m_num * 100000000)); //value sb.EmitParamJson(array); //参数倒序入 sb.EmitParamJson(new MyJson.JsonNode_ValueString("(str)transfer")); //参数倒序入 ThinNeo.Hash160 shash = new ThinNeo.Hash160(global.id_sgas); sb.EmitAppCall(shash); //nep5脚本 //拼接发给后台做验证的json字符串 MyJson.JsonNode_Object account = new MyJson.JsonNode_Object(); account["sbParamJson"] = array; account["sbPushString"] = new MyJson.JsonNode_ValueString("(str)transfer"); account["nnc"] = new MyJson.JsonNode_ValueString(global.id_sgas); script = sb.ToArray(); m_paparms = account.ToString(); Debug.Log(m_paparms); } tran = Helper.makeTran(_dir[global.id_GAS], roleInfo.getInstance().address, new ThinNeo.Hash256(global.id_GAS), 0); tran.type = ThinNeo.TransactionType.InvocationTransaction; var idata = new ThinNeo.InvokeTransData(); tran.extdata = idata; idata.script = script; } //sign and broadcast var signdata = ThinNeo.Helper.Sign(tran.GetMessage(), roleInfo.getInstance().prikey); tran.AddWitness(signdata, roleInfo.getInstance().pubkey, roleInfo.getInstance().address); var trandata = tran.GetRawData(); var strtrandata = ThinNeo.Helper.Bytes2HexString(trandata); transaction_game_sgas(strtrandata); }
public ChainState(Chain chain, Utxo utxo) { this.chain = chain; this.utxo = utxo; }
public void TestSimpleSpend() { // prepare test kernel var kernel = new StandardKernel(new MemoryStorageModule()); // prepare block var fakeHeaders = new FakeHeaders(); var chainedHeader = new ChainedHeader(fakeHeaders.Genesis(), height: 0, totalWork: 0); // prepare an unspent transaction var txHash = new UInt256(100); var unspentTx = new UnspentTx(chainedHeader.Hash, 3, OutputState.Unspent); // prepare unspent output var unspentTransactions = ImmutableDictionary.Create <UInt256, UnspentTx>().Add(txHash, unspentTx); var unspentOutputs = ImmutableDictionary.Create <TxOutputKey, TxOutput>() .Add(new TxOutputKey(txHash, 0), new TxOutput(0, ImmutableArray.Create <byte>())) .Add(new TxOutputKey(txHash, 1), new TxOutput(0, ImmutableArray.Create <byte>())) .Add(new TxOutputKey(txHash, 2), new TxOutput(0, ImmutableArray.Create <byte>())); // mock a parent utxo containing the unspent transaction var mockParentChainStateStorage = new Mock <IChainStateStorage>(); mockParentChainStateStorage.Setup(utxo => utxo.UnspentTransactions()).Returns(unspentTransactions); mockParentChainStateStorage.Setup(utxo => utxo.UnspentOutputs()).Returns(unspentOutputs); var parentUtxo = new Utxo(mockParentChainStateStorage.Object); // initialize memory utxo builder storage var memoryChainStateBuilderStorage = new MemoryChainStateBuilderStorage(mockParentChainStateStorage.Object); kernel.Rebind <IChainStateBuilderStorage>().ToConstant(memoryChainStateBuilderStorage); // initialize utxo builder var chainStateBuilder = new ChainStateBuilder(null, parentUtxo, LogManager.CreateNullLogger(), kernel, null, null, null, null, null); // create an input to spend the unspent transaction's first output var input0 = new TxInput(new TxOutputKey(txHash, txOutputIndex: 0), ImmutableArray.Create <byte>(), 0); var tx0 = new Transaction(0, ImmutableArray.Create(input0), ImmutableArray.Create <TxOutput>(), 0); // spend the input chainStateBuilder.Spend(0, tx0, 0, input0, chainedHeader); // verify utxo storage Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash)); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates.Length == 3); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[0] == OutputState.Spent); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[1] == OutputState.Unspent); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[2] == OutputState.Unspent); // create an input to spend the unspent transaction's second output var input1 = new TxInput(new TxOutputKey(txHash, txOutputIndex: 1), ImmutableArray.Create <byte>(), 0); var tx1 = new Transaction(0, ImmutableArray.Create(input1), ImmutableArray.Create <TxOutput>(), 0); // spend the input chainStateBuilder.Spend(1, tx1, 1, input1, chainedHeader); // verify utxo storage Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash)); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates.Length == 3); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[0] == OutputState.Spent); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[1] == OutputState.Spent); Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[2] == OutputState.Unspent); // create an input to spend the unspent transaction's third output var input2 = new TxInput(new TxOutputKey(txHash, txOutputIndex: 2), ImmutableArray.Create <byte>(), 0); var tx2 = new Transaction(0, ImmutableArray.Create(input2), ImmutableArray.Create <TxOutput>(), 0); // spend the input chainStateBuilder.Spend(2, tx2, 2, input2, chainedHeader); // verify utxo storage Assert.IsFalse(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash)); }
//UtxoManagerのテスト3 public static void Test6() { string basepath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); UtxoFileAccessDB ufadb = new UtxoFileAccessDB(basepath); string ufadbPath = ufadb.GetPath(); if (File.Exists(ufadbPath)) File.Delete(ufadbPath); UtxoFilePointersDB ufpdb = new UtxoFilePointersDB(basepath); string ufpdbPath = ufpdb.GetPath(); if (File.Exists(ufpdbPath)) File.Delete(ufpdbPath); UtxoFilePointersTempDB ufptempdb = new UtxoFilePointersTempDB(basepath); string ufptempdbPath = ufptempdb.GetPath(); if (File.Exists(ufptempdbPath)) File.Delete(ufptempdbPath); UtxoDB utxodb = new UtxoDB(basepath); string utxodbPath = utxodb.GetPath(); if (File.Exists(utxodbPath)) File.Delete(utxodbPath); UtxoManager utxom = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); int length = 100; Sha256Ripemd160Hash[] addrs = new Sha256Ripemd160Hash[length]; long[] bis = new long[length]; int[] tis = new int[length]; int[] tois = new int[length]; Creacoin[] cs = new Creacoin[length]; for (int i = 0; i < length; i++) { addrs[i] = new Sha256Ripemd160Hash(BitConverter.GetBytes(i)); bis[i] = 65536.RandomNum(); tis[i] = 65536.RandomNum(); tois[i] = 65536.RandomNum(); cs[i] = new Creacoin(65536.RandomNum()); } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); utxodb.Open(); for (int i = 0; i < length; i++) utxom.AddUtxo(addrs[i], bis[i], tis[i], tois[i], cs[i]); utxom.SaveUFPTemp(); utxodb.Close(); stopwatch.Stop(); Console.WriteLine(string.Join(":", "test6_5", stopwatch.ElapsedMilliseconds.ToString() + "ms")); UtxoManager utxom2 = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); Utxo[] utxos = new Utxo[length]; stopwatch.Reset(); stopwatch.Start(); utxodb.Open(); for (int i = 0; i < length; i++) utxos[i] = utxom.FindUtxo(addrs[i], bis[i], tis[i], tois[i]); utxodb.Close(); stopwatch.Stop(); Console.WriteLine(string.Join(":", "test6_6", stopwatch.ElapsedMilliseconds.ToString() + "ms")); for (int i = 0; i < length; i++) { if (utxos[i].blockIndex != bis[i]) throw new Exception("test6_1"); if (utxos[i].txIndex != tis[i]) throw new Exception("test6_2"); if (utxos[i].txOutIndex != tois[i]) throw new Exception("test6_3"); if (utxos[i].amount.rawAmount != cs[i].rawAmount) throw new Exception("test6_4"); } }
public CoreDaemon(Logger logger, IKernel kernel, IBlockchainRules rules, BlockHeaderCache blockHeaderCache, ChainedHeaderCache chainedHeaderCache, BlockTxHashesCache blockTxHashesCache, TransactionCache transactionCache, BlockCache blockCache) { this.logger = logger; this.shutdownToken = new CancellationTokenSource(); this.kernel = kernel; this.rules = rules; this.blockHeaderCache = blockHeaderCache; this.chainedHeaderCache = chainedHeaderCache; this.blockTxHashesCache = blockTxHashesCache; this.transactionCache = transactionCache; this.blockCache = blockCache; // write genesis block out to storage this.blockHeaderCache[this.rules.GenesisBlock.Hash] = this.rules.GenesisBlock.Header; this.blockCache[this.rules.GenesisBlock.Hash] = this.rules.GenesisBlock; this.chainedHeaderCache[this.rules.GenesisChainedHeader.Hash] = this.rules.GenesisChainedHeader; // wire up cache events this.blockHeaderCache.OnAddition += OnBlockHeaderAddition; this.blockHeaderCache.OnModification += OnBlockHeaderModification; this.blockCache.OnAddition += OnBlockAddition; this.blockCache.OnModification += OnBlockModification; this.blockTxHashesCache.OnAddition += OnBlockTxHashesAddition; this.blockTxHashesCache.OnModification += OnBlockTxHashesModification; this.chainedHeaderCache.OnAddition += OnChainedHeaderAddition; this.chainedHeaderCache.OnModification += OnChainedHeaderModification; // create chain state builder this.chainStateBuilder = this.kernel.Get <ChainStateBuilder>( new ConstructorArgument("chain", Chain.CreateForGenesisBlock(this.rules.GenesisChainedHeader).ToBuilder()), new ConstructorArgument("parentUtxo", Utxo.CreateForGenesisBlock(this.rules.GenesisBlock.Hash))); this.chainStateLock = new ReaderWriterLockSlim(); // create workers this.chainingWorker = kernel.Get <ChainingWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromSeconds(30)))); this.targetChainWorker = kernel.Get <TargetChainWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromSeconds(30)))); this.chainStateWorker = kernel.Get <ChainStateWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.FromSeconds(5))), new ConstructorArgument("getTargetChain", (Func <Chain>)(() => this.targetChainWorker.TargetChain)), new ConstructorArgument("targetChainWorker", this.targetChainWorker), new ConstructorArgument("chainStateBuilder", this.chainStateBuilder)); this.targetChainWorker.OnTargetBlockChanged += () => { var handler = this.OnTargetBlockChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.targetChainWorker.OnTargetChainChanged += () => { this.chainStateWorker.NotifyWork(); var handler = this.OnTargetChainChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.chainStateWorker.OnChainStateChanged += () => { this.utxoScanWorker.NotifyWork(); //TODO once fully synced, this should save off the immutable snapshot immediately //TODO this will allow there to always be an active chain state once synced this.chainStateLock.DoWrite(() => this.chainState = null); var handler = this.OnChainStateChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.gcWorker = new WorkerMethod("GC Worker", () => { this.logger.Info( string.Join("\n", new string('-', 80), "GC Memory: {0,10:#,##0.00} MB", "Process Memory: {1,10:#,##0.00} MB", new string('-', 80) ) .Format2 ( /*0*/ (float)GC.GetTotalMemory(false) / 1.MILLION(), /*1*/ (float)Process.GetCurrentProcess().PrivateMemorySize64 / 1.MILLION() )); }, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(30), maxIdleTime: TimeSpan.FromSeconds(30), logger: this.logger); this.utxoScanWorker = new WorkerMethod("UTXO Scan Worker", () => { var chainStateLocal = this.GetChainState(); if (chainStateLocal == null) { return; } new MethodTimer().Time("Full UTXO Scan: {0:#,##0}".Format2(chainStateLocal.Utxo.OutputCount), () => { var sha256 = new SHA256Managed(); foreach (var output in chainStateLocal.Utxo.GetUnspentOutputs()) { if (new UInt256(sha256.ComputeDoubleHash(output.Value.ScriptPublicKey.ToArray())) == UInt256.Zero) { } } }); }, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: this.logger); }