private void OnCoinsChanged(WalletDataContext ctx, IEnumerable <WalletCoin> added, IEnumerable <WalletCoin> changed, IEnumerable <WalletCoin> deleted, IEnumerable <JSWalletCoin> jsadded, IEnumerable <JSWalletCoin> jschanged, IEnumerable <JSWalletCoin> jsdeleted, IEnumerable <JSWalletCoin> jswitnesschanged, IEnumerable <RCTWalletCoin> rctadded, IEnumerable <RCTWalletCoin> rctchanged, IEnumerable <RCTWalletCoin> rctdeleted) { #region Transparent Coin foreach (WalletCoin coin in added) { try { ctx.Coins.Add(new Coin { TxId = coin.Reference.PrevHash.ToArray(), Index = coin.Reference.PrevIndex, AssetId = coin.Output.AssetId.ToArray(), Value = coin.Output.Value.GetData(), ScriptHash = coin.Output.ScriptHash.ToArray(), State = coin.State }); ctx.SaveChanges(); } catch (Exception) { } } foreach (WalletCoin coin in changed) { ctx.Coins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex).State = coin.State; try { ctx.Coins.Update(ctx.Coins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex)); ctx.SaveChanges(); } catch (Exception) { } } foreach (WalletCoin coin in deleted) { try { Coin unspent_coin = ctx.Coins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex); ctx.Coins.Remove(unspent_coin); ctx.SaveChanges(); } catch (Exception) { } } #endregion #region ZK-SNARKS Coin foreach (JSWalletCoin coin in jsadded) { ctx.JSCoins.Add(new JSCoin { TxId = coin.Reference.PrevHash.ToArray(), JsId = coin.Reference.PrevJsId, Index = coin.Reference.PrevIndex, AssetId = coin.Output.AssetId.ToArray(), Value = coin.Output.Value.GetData(), ScriptHash = coin.Output.ScriptHash.ToArray(), State = coin.State, r = coin.Output.r.ToArray(), rho = coin.Output.rho.ToArray(), Witness = coin.Output.witness, WitnessHeight = coin.Output.witness_height, CMTreeHeight = coin.Output.cmtree_height }); try { ctx.SaveChanges(); } catch (Exception ex) { string error = ex.Message; } } foreach (JSWalletCoin coin in jschanged) { ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).State = coin.State; ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).Witness = coin.Output.witness; ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).WitnessHeight = coin.Output.witness_height; ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).CMTreeHeight = coin.Output.cmtree_height; try { ctx.SaveChanges(); } catch (Exception ex) { string error = ex.Message; } } foreach (JSWalletCoin coin in jsdeleted) { JSCoin unspent_coin = ctx.JSCoins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId); ctx.JSCoins.Remove(unspent_coin); } foreach (JSWalletCoin coin in jswitnesschanged) { JSCoin update_coin = ctx.JSCoins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId); if (update_coin != null) { try { update_coin.Witness = coin.Output.witness; update_coin.WitnessHeight = coin.Output.witness_height; ctx.JSCoins.Update(update_coin); ctx.SaveChanges(); } catch (Exception ex) { string error = ex.Message; } } } #endregion #region RingCT Coin foreach (RCTWalletCoin coin in rctadded) { ctx.RCTCoins.Add(new RCTCoin { TxId = coin.Reference.PrevHash.ToArray(), TxRCTHash = coin.Reference.TxRCTHash.ToArray(), RctID = coin.Reference.PrevRCTSigId, Index = coin.Reference.PrevRCTSigIndex, AssetId = coin.Output.AssetId.ToArray(), Value = coin.Output.Value.GetData(), PubKey = coin.Output.PubKey.ToArray(), ScriptHash = coin.Output.ScriptHash.ToArray(), State = coin.State }); try { ctx.SaveChanges(); } catch (Exception ex) { string error = ex.Message; } } foreach (RCTWalletCoin coin in rctchanged) { ctx.RCTCoins.First(p => p.TxRCTHash.SequenceEqual(coin.Reference.TxRCTHash.ToArray()) && p.RctID == coin.Reference.PrevRCTSigId && p.Index == coin.Reference.PrevRCTSigIndex).State = coin.State; try { ctx.SaveChanges(); } catch (Exception ex) { string error = ex.Message; } } foreach (RCTWalletCoin coin in rctdeleted) { RCTCoin unspent_coin = ctx.RCTCoins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.RctID == coin.Reference.PrevRCTSigId && p.Index == coin.Reference.PrevRCTSigIndex); ctx.RCTCoins.Remove(unspent_coin); } #endregion }
protected override void OnProcessNewBlock(Block block, IEnumerable <WalletCoin> added, IEnumerable <WalletCoin> changed, IEnumerable <WalletCoin> deleted, IEnumerable <JSWalletCoin> jsadded, IEnumerable <JSWalletCoin> jschanged, IEnumerable <JSWalletCoin> jsdeleted, IEnumerable <JSWalletCoin> jswitnesschanged, IEnumerable <RCTWalletCoin> rctadded, IEnumerable <RCTWalletCoin> rctchanged, IEnumerable <RCTWalletCoin> rctdeleted) { Transaction[] tx_changed = null; using (WalletDataContext ctx = new WalletDataContext(DbPath)) { foreach (CoreTransaction tx in block.Transactions.Where(p => IsWalletTransaction(p))) { Transaction db_tx = ctx.Transactions.FirstOrDefault(p => p.Hash.SequenceEqual(tx.Hash.ToArray())); if (db_tx == null) { ctx.Transactions.Add(new Transaction { Hash = tx.Hash.ToArray(), Type = tx.Type, RawData = tx.ToArray(), Height = block.Index, Time = block.Timestamp.ToDateTime() }); } else { db_tx.Height = block.Index; } } tx_changed = ctx.ChangeTracker.Entries <Transaction>().Where(p => p.State != EntityState.Unchanged).Select(p => p.Entity).ToArray(); OnCoinsChanged(ctx, added, changed, deleted, jsadded, jschanged, jsdeleted, jswitnesschanged, rctadded, rctchanged, rctdeleted); if (block.Index == Blockchain.Default.Height || ctx.ChangeTracker.Entries().Any()) { foreach (Transaction db_tx in ctx.Transactions.Where(p => !p.Height.HasValue)) { if (block.Transactions.Any(p => p.Hash == new UInt256(db_tx.Hash))) { db_tx.Height = block.Index; } } ctx.Keys.First(p => p.Name == "Height").Value = BitConverter.GetBytes(WalletHeight); ctx.Keys.First(p => p.Name == "CmMerkleTree").Value = GetCmMerkleTreeInBytes(); try { ctx.SaveChanges(); } catch (Exception ex) { string str = ex.Message; } } } if (tx_changed?.Length > 0) { TransactionsChanged?.Invoke(this, GetTransactionInfo(tx_changed)); } }