public async Task <Block> GetBlock(string id) { return(await _blockProvider.GetBlock(id)); }
public void Process(Chain mainChain, IBlockProvider blockProvider) { bool newChain = false; if(!Chain.Initialized) { newChain = true; var firstBlock = mainChain.GetBlock(StartHeight); Chain.Initialize(firstBlock.Header, StartHeight); } var forkBlock = mainChain.FindFork(Chain); if(forkBlock.HashBlock != Chain.Tip.HashBlock) { Chain.SetTip(Chain.GetBlock(forkBlock.Height)); foreach(var e in Account.GetInChain(Chain, false) .Where(e => e.Reason != AccountEntryReason.ChainBlockChanged)) { var neutralized = e.Neutralize(); Account.PushAccountEntry(neutralized); } } var unprocessedBlocks = mainChain.ToEnumerable(true) .TakeWhile(block => block != forkBlock) .Concat(newChain ? new ChainedBlock[] { forkBlock } : new ChainedBlock[0]) .Reverse().ToArray(); foreach(var block in unprocessedBlocks) { List<byte[]> searchedData = new List<byte[]>(); Scanner.GetScannedPushData(searchedData); foreach(var unspent in Account.Unspent) { searchedData.Add(unspent.OutPoint.ToBytes()); } var fullBlock = blockProvider.GetBlock(block.HashBlock, searchedData); if(fullBlock != null) { foreach(var spent in Scanner.FindSpent(fullBlock, Account.Unspent)) { var entry = new AccountEntry(AccountEntryReason.Outcome, block.HashBlock, spent, -spent.TxOut.Value); Account.PushAccountEntry(entry); } foreach(var coins in Scanner.ScanCoins(fullBlock, (int)block.Height)) { int i = 0; foreach(var output in coins.Coins.Outputs) { if(!output.IsNull) { var entry = new AccountEntry(AccountEntryReason.Income, block.HashBlock, new Spendable(new OutPoint(coins.TxId, i), output), output.Value); Account.PushAccountEntry(entry); } i++; } } } Chain.GetOrAdd(block.Header); } }
public void Process(Chain mainChain, IBlockProvider blockProvider) { bool newChain = false; if (!Chain.Initialized) { newChain = true; var firstBlock = mainChain.GetBlock(StartHeight); Chain.Initialize(firstBlock.Header, StartHeight); } var forkBlock = mainChain.FindFork(Chain); if (forkBlock.HashBlock != Chain.Tip.HashBlock) { Chain.SetTip(Chain.GetBlock(forkBlock.Height)); foreach (var e in Account.GetInChain(Chain, false) .Where(e => e.Reason != AccountEntryReason.ChainBlockChanged)) { var neutralized = e.Neutralize(); Account.PushAccountEntry(neutralized); } } var unprocessedBlocks = mainChain.ToEnumerable(true) .TakeWhile(block => block != forkBlock) .Concat(newChain ? new ChainedBlock[] { forkBlock } : new ChainedBlock[0]) .Reverse().ToArray(); foreach (var block in unprocessedBlocks) { List <byte[]> searchedData = new List <byte[]>(); Scanner.GetScannedPushData(searchedData); foreach (var unspent in Account.Unspent) { searchedData.Add(unspent.OutPoint.ToBytes()); } var fullBlock = blockProvider.GetBlock(block.HashBlock, searchedData); if (fullBlock != null) { foreach (var spent in Scanner.FindSpent(fullBlock, Account.Unspent)) { var entry = new AccountEntry(AccountEntryReason.Outcome, block.HashBlock, spent, -spent.TxOut.Value); Account.PushAccountEntry(entry); } foreach (var coins in Scanner.ScanCoins(fullBlock, (int)block.Height)) { int i = 0; foreach (var output in coins.Coins.Outputs) { if (!output.IsNull) { var entry = new AccountEntry(AccountEntryReason.Income, block.HashBlock, new Spendable(new OutPoint(coins.TxId, i), output), output.Value); Account.PushAccountEntry(entry); } i++; } } } Chain.GetOrAdd(block.Header); } }
public bool Process(ChainBase mainChain, IBlockProvider blockProvider) { var chainCopy = Chain.Clone(); var chainPosition = chainCopy.Changes.Position; var accountCopy = Account.Clone(); var accountPosition = accountCopy.Entries.Position; bool newChain = false; if (!chainCopy.Initialized) { newChain = true; var firstBlock = mainChain.GetBlock(StartHeight); chainCopy.Initialize(firstBlock.Header, StartHeight); } var forkBlock = mainChain.FindFork(chainCopy); if (forkBlock.HashBlock != chainCopy.Tip.HashBlock) { var subChain = chainCopy.CreateSubChain(forkBlock, false, chainCopy.Tip, true); chainCopy.SetTip(chainCopy.GetBlock(forkBlock.Height)); foreach (var e in accountCopy.GetInChain(subChain, true) .Where(c => c.Reason != AccountEntryReason.Lock && c.Reason != AccountEntryReason.Unlock) .Reverse()) { var neutralized = e.Neutralize(); accountCopy.PushAccountEntry(neutralized); } } var unprocessedBlocks = mainChain.ToEnumerable(true) .TakeWhile(block => block != forkBlock) .Concat(newChain ? new ChainedBlock[] { forkBlock } : new ChainedBlock[0]) .Reverse().ToArray(); foreach (var block in unprocessedBlocks) { List <byte[]> searchedData = new List <byte[]>(); Scanner.GetScannedPushData(searchedData); foreach (var unspent in accountCopy.Unspent) { searchedData.Add(unspent.OutPoint.ToBytes()); } var fullBlock = blockProvider.GetBlock(block.HashBlock, searchedData); if (fullBlock == null) { continue; } List <Tuple <OutPoint, AccountEntry> > spents = new List <Tuple <OutPoint, AccountEntry> >(); foreach (var spent in FindSpent(fullBlock, accountCopy.Unspent)) { var entry = new AccountEntry(AccountEntryReason.Outcome, block.HashBlock, spent.Spendable, -spent.Spendable.TxOut.Value, spent.TxId); spents.Add(Tuple.Create(entry.Spendable.OutPoint, entry)); } if (CheckDoubleSpend) { var spentsDico = spents.ToDictionary(t => t.Item1, t => t.Item2); foreach (var spent in Scanner.FindSpent(fullBlock)) { if (!spentsDico.ContainsKey(spent.PrevOut)) { return(false); } } } foreach (var spent in spents) { if (accountCopy.PushAccountEntry(spent.Item2) == null) { return(false); } } foreach (var coins in Scanner.ScanCoins(fullBlock, (int)block.Height)) { int i = 0; foreach (var output in coins.Coins.Outputs) { if (!output.IsNull) { var entry = new AccountEntry(AccountEntryReason.Income, block.HashBlock, new Spendable(new OutPoint(coins.TxId, i), output), output.Value, null); if (accountCopy.PushAccountEntry(entry) == null) { return(false); } } i++; } } chainCopy.SetTip(block); } accountCopy.Entries.GoTo(accountPosition); Account.PushAccountEntries(accountCopy.Entries); chainCopy.Changes.GoTo(chainPosition); Chain.PushChanges(chainCopy.Changes); return(true); }
public bool Process(Chain mainChain, IBlockProvider blockProvider) { var chain = Chain.Clone(); var chainPosition = chain.Changes.Position; var account = Account.Clone(); var accountPosition = account.Entries.Position; bool newChain = false; if(!chain.Initialized) { newChain = true; var firstBlock = mainChain.GetBlock(StartHeight); chain.Initialize(firstBlock.Header, StartHeight); } var forkBlock = mainChain.FindFork(chain); if(forkBlock.HashBlock != chain.Tip.HashBlock) { var subChain = chain.CreateSubChain(forkBlock, false, chain.Tip, true); chain.SetTip(chain.GetBlock(forkBlock.Height)); foreach(var e in account.GetInChain(subChain, true) .Where(c => c.Reason != AccountEntryReason.Lock && c.Reason != AccountEntryReason.Unlock) .Reverse()) { var neutralized = e.Neutralize(); account.PushAccountEntry(neutralized); } } var unprocessedBlocks = mainChain.ToEnumerable(true) .TakeWhile(block => block != forkBlock) .Concat(newChain ? new ChainedBlock[] { forkBlock } : new ChainedBlock[0]) .Reverse().ToArray(); foreach(var block in unprocessedBlocks) { List<byte[]> searchedData = new List<byte[]>(); Scanner.GetScannedPushData(searchedData); foreach(var unspent in account.Unspent) { searchedData.Add(unspent.OutPoint.ToBytes()); } var fullBlock = blockProvider.GetBlock(block.HashBlock, searchedData); if(fullBlock == null) continue; List<Tuple<OutPoint, AccountEntry>> spents = new List<Tuple<OutPoint, AccountEntry>>(); foreach(var spent in FindSpent(fullBlock, account.Unspent)) { var entry = new AccountEntry(AccountEntryReason.Outcome, block.HashBlock, spent, -spent.TxOut.Value); spents.Add(Tuple.Create(entry.Spendable.OutPoint, entry)); } if(CheckDoubleSpend) { var spentsDico = spents.ToDictionary(t => t.Item1, t => t.Item2); foreach(var spent in Scanner.FindSpent(fullBlock)) { if(!spentsDico.ContainsKey(spent.PrevOut)) return false; } } foreach(var spent in spents) { if(account.PushAccountEntry(spent.Item2) == null) return false; } foreach(var coins in Scanner.ScanCoins(fullBlock, (int)block.Height)) { int i = 0; foreach(var output in coins.Coins.Outputs) { if(!output.IsNull) { var entry = new AccountEntry(AccountEntryReason.Income, block.HashBlock, new Spendable(new OutPoint(coins.TxId, i), output), output.Value); if(account.PushAccountEntry(entry) == null) return false; } i++; } } chain.GetOrAdd(block.Header); } account.Entries.GoTo(accountPosition); Account.Entries.WriteNext(account.Entries); Account.Process(); chain.Changes.GoTo(chainPosition); Chain.Changes.WriteNext(chain.Changes); Chain.Process(); return true; }