Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add checks for obsolete data #119

Merged
merged 1 commit into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Discreet/DB/ChainDB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ public ChainDB(string path)
}
}

internal void ForceCloseAndWipe()
{
DropAllData();
}

public IEnumerable<Block> GetBlocks(long startHeight, long limit)
{
if (limit <= 0) limit = long.MaxValue;
Expand Down Expand Up @@ -400,6 +405,53 @@ public void DropEverything(string path)
rdb?.Dispose();
}

internal void DropAllData()
{
if (rdb != null)
{
indexer_output = new U32(0);
indexer_tx = new U64(0);
height = new L64(-1);

DropAllInColumn(Txs);
DropAllInColumn(TxIndices);
DropAllInColumn(BlockHeights);
DropAllInColumn(Blocks);
DropAllInColumn(BlockHeaders);
DropAllInColumn(BlockCache);
DropAllInColumn(SpentKeys);
DropAllInColumn(Outputs);
DropAllInColumn(OutputIndices);
DropAllInColumn(PubOutputs);
DropAllInColumn(Meta);

// rebuild meta
rdb.Put(Encoding.ASCII.GetBytes("meta"), ZEROKEY, cf: Meta);
rdb.Put(Encoding.ASCII.GetBytes("indexer_tx"), Serialization.UInt64(indexer_tx.Value), cf: Meta);
rdb.Put(Encoding.ASCII.GetBytes("indexer_output"), Serialization.UInt32(indexer_output.Value), cf: Meta);
rdb.Put(Encoding.ASCII.GetBytes("height"), Serialization.Int64(height.Value), cf: Meta);
}
}

internal void DropAllInColumn(ColumnFamilyHandle h)
{
var iter = rdb.NewIterator(cf: h);
iter = iter.SeekToFirst();
List<byte[]> k2r = new List<byte[]>();
while (iter.Valid())
{
k2r.Add(iter.Key());
iter = iter.Next();
}

foreach (var k in k2r)
{
rdb.Remove(k, cf: h);
}

iter.Dispose();
}

public Dictionary<long, Block> GetBlockCache()
{
Dictionary<long, Block> blockCache = new Dictionary<long, Block>();
Expand Down
2 changes: 2 additions & 0 deletions Discreet/DB/CurView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ public CurView()
chainDB = new ChainDB(Path.Join(Daemon.DaemonConfig.GetConfig().DBPath, "chain"));
}

internal void ForceCloseAndWipe() => chainDB.ForceCloseAndWipe();

public IEnumerable<Block> GetBlocks(long startHeight, long limit) => chainDB.GetBlocks(startHeight, limit);
public void AddBlockToCache(Block blk) => chainDB.AddBlockToCache(blk);

Expand Down
2 changes: 2 additions & 0 deletions Discreet/DB/DataView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public DataView()
curView = new CurView();
}

internal void ForceCloseAndWipe() => curView.ForceCloseAndWipe();

public IEnumerable<Block> GetBlocks(long startHeight, long limit) => curView.GetBlocks(startHeight, limit);

public void AddBlockToCache(Block blk) => curView.AddBlockToCache(blk);
Expand Down
30 changes: 29 additions & 1 deletion Discreet/Daemon/Daemon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Discreet.Daemon.BlockAuth;
using System.Threading.Channels;
using Discreet.DB;
using Discreet.Network.Peerbloom;

namespace Discreet.Daemon
{
Expand Down Expand Up @@ -63,6 +64,28 @@ public class Daemon

public Daemon()
{
// check if the chain has been updated
var db = DB.DataView.GetView();
if (db.GetChainHeight() >= 0)
{
var block = db.GetBlock(db.GetChainHeight());
if (block.Header.Extra != null && block.Header.Extra.Length == 96)
{
var sig = new Signature(block.Header.Extra);
if (Block.IsBlockAuthority(sig.y) && !AuthKeys.Defaults.Any(x => x == sig.y))
{
// our chain is outdated, wipe everything and peerlist
Logger.Critical("Detected outdated peerlist and blockchain; wiping and forcing resync");
db.ForceCloseAndWipe();
network = Network.Peerbloom.Network.GetNetwork(true);
DefaultBlockAuth.Instance.Keyring.Keys = new List<Key>(AuthKeys.Defaults);
DaemonConfig.GetConfig().AuConfig.AuthorityKeys = new List<string>(AuthKeys.Defaults.Select(x => x.ToHex()));
DaemonConfig.GetConfig().Save();
Logger.Critical("Finished wipe.");
}
}
}

txpool = TXPool.GetTXPool();
network = Network.Peerbloom.Network.GetNetwork();
messageCache = Network.MessageCache.GetMessageCache();
Expand All @@ -71,9 +94,14 @@ public Daemon()
config = DaemonConfig.GetConfig();

_versionBackgroundPoller = new Version.VersionBackgroundPoller();
var pingStr = "";
if (DaemonConfig.GetConfig().PingOnUpdateAvailable.Value)
{
pingStr = "\a";
}
_versionBackgroundPoller.UpdateAvailable += (localVersion, newVersion) =>
{
Logger.Warn($"New version available: {newVersion.ToString(3)} - currently running on version: {localVersion.ToString(3)}");
Logger.Warn($"New version available: {newVersion.ToString(3)} - currently running on version: {localVersion.ToString(3)}{pingStr}");
};

signingKey = Key.FromHex(config.SigningKey);
Expand Down
9 changes: 9 additions & 0 deletions Discreet/Daemon/DaemonConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ public void ConfigureDefaults()
NetworkVersion = 1;
}

if (PingOnUpdateAvailable == null)
{
PingOnUpdateAvailable = false;
}

if (IsPublic == null)
{
IsPublic = false;
Expand Down Expand Up @@ -279,6 +284,8 @@ public static void SetConfig(DaemonConfig config)
public byte? NetworkID { get; set; }
public uint? NetworkVersion { get; set; }

public bool? PingOnUpdateAvailable { get; set; }

public bool? IsPublic { get; set; }

public string SigningKey { get; set; }
Expand Down Expand Up @@ -327,6 +334,8 @@ public DaemonConfig()
NetworkID = 1;
NetworkVersion = 1;

PingOnUpdateAvailable = false;

IsPublic = false;

RPCPort = 8350;
Expand Down
12 changes: 6 additions & 6 deletions Discreet/Network/Peerbloom/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ public class Network

private static object network_lock = new object();

public static Network GetNetwork()
public static Network GetNetwork(bool forceWipePeers = false)
{
lock (network_lock)
{
if (_network == null) Instantiate();
if (_network == null) Instantiate(forceWipePeers);

return _network;
}
}

public static void Instantiate()
public static void Instantiate(bool forceWipePeers = false)
{
lock (network_lock)
{
Daemon.Logger.Debug($"Network.Instantiate: network is being instantiated");
if (_network == null) _network = new Network(Daemon.DaemonConfig.GetConfig().Endpoint);
if (_network == null) _network = new Network(Daemon.DaemonConfig.GetConfig().Endpoint, forceWipePeers);
}
}

Expand Down Expand Up @@ -318,12 +318,12 @@ public void RemoveNodeFromPool(Connection node)
/// <summary>
/// Default constructor for the network class
/// </summary>
public Network(IPEndPoint endpoint)
public Network(IPEndPoint endpoint, bool wipePeerlist = false)
{
LocalNode = new LocalNode(endpoint);
Cache = MessageCache.GetMessageCache();
_shutdownTokenSource = new CancellationTokenSource();
peerlist = new Peerlist();
peerlist = new Peerlist(wipePeerlist);
feeler = new Feeler(this, peerlist);
IncomingTester = new IncomingTester(this, peerlist);
}
Expand Down
23 changes: 13 additions & 10 deletions Discreet/Network/Peerbloom/Peerlist.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,25 @@ public Peerlist(string path)
return;
}

public Peerlist()
public Peerlist(bool forceWipePeers = false)
{
var path = Path.Combine(Daemon.DaemonConfig.GetConfig().DaemonPath, "peerlist.bin");
if (File.Exists(path))
if (!forceWipePeers)
{
try
if (File.Exists(path))
{
Deserialize(File.ReadAllBytes(path));
return;
}
catch
{
Daemon.Logger.Error($"Peerlist: could not initialize from {path}; possibly corrupt");
try
{
Deserialize(File.ReadAllBytes(path));
return;
}
catch
{
Daemon.Logger.Error($"Peerlist: could not initialize from {path}; possibly corrupt");
}
}
}

_counter = 1;
_newCounter = 0;
_triedCounter = 0;
Expand Down
44 changes: 44 additions & 0 deletions Discreet/Wallets/Extensions/AccountEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,51 @@
{
public static class AccountEx
{
public static List<UTXO> CheckObsoleteUTXOs(this Account account)
{
List<UTXO> invalid = new();

if (account.Encrypted) throw new Exception("account is still encrypted");
// check against utxos in this account
foreach (var ux in account.UTXOs)
{
if (ux.Type == 0)
{
// try fetch private utxo from index
try
{
var otherUTXO = ViewProvider.GetDefaultProvider().GetOutput(ux.Index);
if (otherUTXO.TransactionSrc != ux.TransactionSrc || otherUTXO.Commitment != ux.Commitment || otherUTXO.UXKey != ux.UXKey)
{
invalid.Add(ux);
}
}
catch (Exception ex)
{
invalid.Add(ux);
}
}
else
{
try
{
var otherTrsp = ViewProvider.GetDefaultProvider().GetPubOutput(new TTXInput { TxSrc = ux.TransactionSrc, Offset = (byte)ux.Index });
if (otherTrsp.TransactionSrc != ux.TransactionSrc || otherTrsp.Address.ToString() != ux.Address || ux.Amount != otherTrsp.Amount)
{
invalid.Add(ux);
}
}
catch (Exception ex)
{
invalid.Add(ux);
}
}
}

return invalid;
}

public static (List<UTXO>? spents, List<UTXO>? utxos, List<HistoryTx>? htxs) ProcessBlock(this Account account, Block block)

Check warning on line 67 in Discreet/Wallets/Extensions/AccountEx.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 67 in Discreet/Wallets/Extensions/AccountEx.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
{
List<UTXO> utxos = new();
List<HistoryTx> txs = new();
Expand Down
18 changes: 18 additions & 0 deletions Discreet/Wallets/SQLiteWallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using Discreet.Cipher.Mnemonics;
using System.Reflection.Emit;
using Discreet.Coin.Models;
using Discreet.Wallets.Extensions;

namespace Discreet.Wallets
{
Expand Down Expand Up @@ -368,6 +369,12 @@ public void DeleteKey(string name)

public static SQLiteWallet CreateWallet(CreateWalletParameters parameters)
{
// check if the wallet name is null or empty
if (string.IsNullOrEmpty(parameters.Label))
{
throw new FormatException($"{nameof(parameters.Label)} is null or empty");
}

// first check if wallet with label already exists
var labels = Directory.GetFiles(directory, "*.db")
.Select(file => System.IO.Path.GetFileNameWithoutExtension(file));
Expand Down Expand Up @@ -562,6 +569,11 @@ private Account CreateAccount(CreateAccountParameters parameters)
account.Deterministic = parameters.Deterministic;
account.Type = parameters.Type;

if (string.IsNullOrEmpty(parameters.Name))
{
throw new FormatException(nameof(parameters.Name) + " is null or empty");
}

if (account.Deterministic)
{
if (account.Type == 0)
Expand Down Expand Up @@ -910,6 +922,12 @@ public List<Account> LoadAccounts()
acc.TxHistory = new HashSet<HistoryTx>(txs, new HistoryTxEqualityComparer());

acc.SelectedUTXOs = new(new UTXOEqualityComparer());
// check if invalid utxos
var inv = acc.CheckObsoleteUTXOs();
if (inv != null && inv.Count > 0)
{
SaveAccountFundData(acc, inv, Enumerable.Empty<UTXO>(), Enumerable.Empty<HistoryTx>());
}

var lshb = LoadKey(acc.Address);
if (lshb != null)
Expand Down
Loading