Skip to content

Commit

Permalink
Still needs to solv a problem on the Remove method.
Browse files Browse the repository at this point in the history
  • Loading branch information
rodoufu committed Nov 11, 2018
1 parent 0017b5d commit 9eb5d32
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 35 deletions.
96 changes: 71 additions & 25 deletions NeoDataStructure/MerklePatricia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ public string this[string key]
}

/// <summary>
/// Test is contains a specific key.
/// Test if contains a specific key.
/// </summary>
/// <param name="key">Key to be tested.</param>
/// <returns>true in the case the tree contains the key.</returns>
public bool ContainsKey(string key) => this[key] != null;

/// <summary>
/// Test if the tree contains a specific value.
/// Takes O(n) operations.
/// </summary>
/// <param name="value">Value to look for.</param>
/// <returns>true if the value is present.</returns>
public bool ContainsValue(string value) => _db.Any(x => x.Value[x.Value.Length - 1] == value);

private string Get(string[] node, string path)
{
while (true)
Expand Down Expand Up @@ -121,52 +129,88 @@ public bool Remove(string key)
}

var removido = Remove(_rootHash, key.CompactEncodeString());
_db.Remove(_rootHash);
var resp = removido != _rootHash;
_rootHash = removido;
if (resp)
{
_db.Remove(_rootHash);
}

_rootHash = removido;
return resp;
}

private string Remove(string nodeHash, string path)
{
var node = _db[nodeHash];
switch (node.Length)
if (node.Length == 0)
{
case LeafSize when node[0].Substring(1) == path:
_db.Remove(nodeHash);
return null;
case LeafSize:
return nodeHash;
return null;
}

int kint = path.Substring(0, 1).FromHex();
if (node[kint] == null)
if (node.Length == LeafSize)
{
if (node[0].Substring(1) == path)
{
_db.Remove(nodeHash);
return null;
}

_db[nodeHash] = node;
return nodeHash;
}

var innerNodeHash = Remove(node[kint], path.Substring(1));
if (node[kint] != innerNodeHash)
if (path.IsEmpty())
{
_db.Remove(node[kint]);
node[kint] = innerNodeHash;
if (node[node.Length - 2] == null && node.Count(x => x != null) == 1)
node[node.Length - 2] = node[node.Length - 1] = null;
}
else
{
int kint = path.Substring(0, 1).FromHex();
if (node[kint] != null)
{
var index = 0;
while (node[index] == null)
var innerHash = Remove(node[kint], path.Substring(1));
if (node[kint] != innerHash)
{
index++;
_db.Remove(node[kint]);
node[kint] = innerHash;

int contar = 0;
int indexInnerNode = 0;
for (int i = 0; i < node.Length - 2; i++)
{
if (node[i] != null)
{
contar++;
indexInnerNode = i;
}
}

if (contar == 0)
{
node = new[] {"2", node[node.Length - 2], node[node.Length - 1]};
}
else if (contar == 1)
{
if (node[node.Length - 1] == null)
{
var innerNode = _db[node[indexInnerNode]];
if (innerNode.Length == LeafSize)
{
node = new[]
{
2 + innerNode[0].Length % 2 + "" + indexInnerNode + innerNode[0].Substring(1),
innerNode[innerNode.Length - 2],
innerNode[innerNode.Length - 1]
};
}
}
}
}

// node = db[node[index]];
}

var removedHash = node.Hash();
_db[removedHash] = node;
return removedHash;
}

nodeHash = node.Hash();
_db[nodeHash] = node;
return nodeHash;
}

Expand Down Expand Up @@ -330,5 +374,7 @@ private string NodeToString(string[] node)
resp.Append("}");
return resp.ToString();
}

public int Count() => _db.Count(x => x.Value[x.Value.Length - 1] != null);
}
}
72 changes: 62 additions & 10 deletions NeoDataStructureTest/MerklePatriciaTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,33 @@ public void ColideKeys()
[Fact]
public void Remove()
{
var merklePatricia = new MerklePatricia();
var mp = new MerklePatricia();

void RemoverTestar(string x, string y)
{
merklePatricia[x] = y;
Assert.True(merklePatricia.ContainsKey(x));
Assert.False(merklePatricia.ContainsKey(x + "123"));
Assert.Equal(y, merklePatricia[x]);
Assert.Null(merklePatricia[x + "123k"]);

Assert.True(merklePatricia.Remove(x));
Assert.False(merklePatricia.Remove(x));
mp[x] = y;
Assert.True(mp.ContainsKey(x));
Assert.False(mp.ContainsKey(x + "123"));
Assert.Equal(y, mp[x]);
Assert.Null(mp[x + "123k"]);

Assert.True(mp.Remove(x));
Assert.False(mp.Remove(x));
}

RemoverTestar("oi", "bala");
// merklePatricia.Remove("oi");
mp.Remove("oi");
Assert.False(mp.ContainsKey("oi"));

mp["123"] = "abc";
mp["a123"] = "1abc";
Assert.Equal(2, mp.Count());

Assert.False(mp.Remove("b123"));
Assert.Equal(2, mp.Count());
Assert.True(mp.Remove("a123"));
// TODO Solve problem on the remove method, not removing from _db
Assert.Equal(1, mp.Count());
}

[Fact]
Expand Down Expand Up @@ -195,5 +206,46 @@ public void PatriciaToString()
mp["oi123"] = "asfbala12";
System.Console.WriteLine($"a:\n {mp}");
}

[Fact]
public void PatriciaCount()
{
var mp = new MerklePatricia();
Assert.Equal(0, mp.Count());

mp["oi"] = "oi";
Assert.Equal(1, mp.Count());

mp["oi"] = "oi";
Assert.Equal(1, mp.Count());

mp["oi"] = "oi1";
Assert.Equal(1, mp.Count());

mp["oi1"] = "oi1";
mp["oi2"] = "oi2";
Assert.Equal(3, mp.Count());

mp["bala"] = "bala2";
Assert.Equal(4, mp.Count());
}

[Fact]
public void ContainsValue()
{
var mp = new MerklePatricia
{
["aoi"] = "oi",
["boi2"] = "oi2",
["coi1"] = "oi3"
};
Assert.True(mp.ContainsValue("oi"));
Assert.True(mp.ContainsValue("oi2"));
Assert.True(mp.ContainsValue("oi3"));

Assert.False(mp.ContainsValue("aoi"));
Assert.False(mp.ContainsValue("boi2"));
Assert.False(mp.ContainsValue("coi3"));
}
}
}

0 comments on commit 9eb5d32

Please sign in to comment.