public bool AddVault(Vault v) { // track stats TotalJoins++; // get prefix for vault var prefix = GetPrefixForXorname(v.Name); Section section = default(Section); // get the section for this prefix if (!Sections.ContainsKey(prefix.Key)) { var blankPrefix = new Prefix(); var netEvt = Section.NewSection(blankPrefix, new List <Vault>()); if (netEvt != null) { foreach (var s in netEvt.NewSections) { section = s; Sections[section.Prefix.Key] = section; } } } else { section = Sections[prefix.Key]; } // add the vault to the section var(ne, disallowed) = section.AddVault(v); // if there was a split if (ne != null && ne.NewSections.Count > 0) { TotalSplits++; // add new sections foreach (var s in ne.NewSections) { Sections[s.Prefix.Key] = s; } // remove old section Sections.Remove(section.Prefix.Key); } // relocate vault if there is one to relocate if (ne != null && ne.VaultToRelocate != null) { RelocateVault(ne); } return(disallowed); }
// @mav: // There should never be a prefix longer than the vault name length (vault name length is constant at 256 bits). // This would mean there’s approx 2^256 sections in the network which is pretty massive. public void RenameWithPrefix(Prefix p) { if (p.Bits.Count > Name.Bits.Count) { Console.WriteLine("Warning: prefix bit count longer than name bit count!"); } var newBits = Name.Bits.Count >= p.Bits.Count ? new BitArray(Name.Bits) : new BitArray(p.Bits); for (int i = 0; i < p.Bits.Count; i++) { newBits.Set(i, p.Bits[i]); } Name = new XorName(newBits); }
public Prefix ExtendLeft() { var newBits = new BitArray(Bits.Count + 1); foreach (int i in Enumerable.Range(0, Bits.Count)) { newBits[i] = Bits[i]; } var left = new Prefix { Bits = newBits }; left.SetKey(); return(left); }
public Prefix Sibling() { var s = new Prefix { Bits = Bits }; if (s.Bits.Count == 0) { Console.WriteLine("Warning: There should be no calling of Sibling on empty prefix!"); } else { s.Bits[s.Bits.Count - 1] = !s.Bits[s.Bits.Count - 1]; } s.SetKey(); return(s); }
public Prefix ExtendRight() { var newBits = new BitArray(Bits.Count + 1); foreach (int i in Enumerable.Range(0, Bits.Count)) { newBits[i] = Bits[i]; } newBits[newBits.Count - 1] = true; var right = new Prefix { Bits = newBits }; right.SetKey(); return(right); }
internal Prefix Parent() { if (Bits.Count == 0) { Console.WriteLine("Warning: There should be no calling of Parent on empty prefix!"); } var newBits = new BitArray(Math.Max(0, Bits.Count - 1)); foreach (int i in Enumerable.Range(0, newBits.Count)) { newBits[i] = Bits[i]; } var a = new Prefix { Bits = newBits }; a.SetKey(); return(a); }
// Returns a slice of sections since as vaults age they may cascade into // multiple sections. public static NetworkEvent NewSection(Prefix prefix, List <Vault> vaults) { var section = new Section { Prefix = prefix, }; // add each existing vault to new section foreach (var vault in vaults) { vault.SetPrefix(section.Prefix); section.Vaults.Add(vault); } // split into two sections if needed. // there is no vault relocation here. if (section.ShouldSplit()) { return(section.Split()); } // return the section as a network event. // there is a vault relocation here. var netEvt = new NetworkEvent { NewSections = new List <Section> { section } }; var toRelocate = section.VaultForRelocation(netEvt); if (toRelocate != null) { netEvt.VaultToRelocate = toRelocate; } return(netEvt); }
Prefix GetPrefixForXorname(XorName x) { var prefix = new Prefix(); while (!Sections.ContainsKey(prefix.Key) && prefix.Bits.Count < x.Bits.Count) { // get the next bit of the xorname prefix // extend the prefix depending on the bit of the xorname if (!x.Bits[prefix.Bits.Count]) { prefix = prefix.ExtendLeft(); } else { prefix = prefix.ExtendRight(); } } if (!Sections.ContainsKey(prefix.Key) && HasMoreThanOneVault()) { Debug.WriteLine("Warning: No prefix for xorname"); return(new Prefix()); } return(prefix); }
int AdultCountForExtendedPrefix(Prefix p) { return(Vaults.Count(v => v.IsAdult() && p.Matches(v.Name))); }
int RightAdultCount() { var rightPrefix = Prefix.ExtendRight(); return(AdultCountForExtendedPrefix(rightPrefix)); }
int LeftAdultCount() { var leftPrefix = Prefix.ExtendLeft(); return(AdultCountForExtendedPrefix(leftPrefix)); }
int VaultCountForExtendedPrefix(Prefix p) { return(Vaults.Count(v => p.Matches(v.Name))); }
public void SetPrefix(Prefix p) { Prefix = p; }
void RelocateVault(NetworkEvent ne) { // track stats for relocations TotalRelocations++; // find the neighbour with shortest prefix or fewest vaults // default to the existing section, useful for zero-length prefix var smallestNeighbour = Sections[ne.VaultToRelocate.Prefix.Key]; var minNeighbourPrefix = UInt32.MaxValue; var minNeighbourVaults = UInt32.MaxValue; // get all neighbours for (int i = 0; i < ne.VaultToRelocate.Prefix.Bits.Count; i++) { // clone the prefix but flip the ith bit of the prefix var neighbourPrefix = new Prefix(); for (int j = 0; j < ne.VaultToRelocate.Prefix.Bits.Count; j++) { var isZero = !(bool)ne.VaultToRelocate.Prefix.Bits[j]; if (j == i) { isZero = !isZero; } if (isZero) { neighbourPrefix = neighbourPrefix.ExtendLeft(); } else { neighbourPrefix = neighbourPrefix.ExtendRight(); } } // get neighbouring prefixes from the network for this prefix // and repeat until we arrive at the 'best' neighbour prefix var prevNeighbourPrefix = new Prefix(); while (!neighbourPrefix.Equals(prevNeighbourPrefix)) { // track previous neighbour prefix prevNeighbourPrefix = neighbourPrefix; // get potential new neighbour prefixes var neighbourPrefixes = GetMatchingPrefixes(neighbourPrefix); // check if these neighbours contain the 'best' neighbour // prioritise sections with shorter prefixes and having less nodes to balance the network foreach (var p in neighbourPrefixes) { var s = Sections[p.Key]; if (p.Bits.Count < minNeighbourPrefix) { // prefer shorter prefixes neighbourPrefix = p; minNeighbourPrefix = (uint)p.Bits.Count; smallestNeighbour = s; } else if (p.Bits.Count == minNeighbourPrefix) { // prefer less vaults if prefix length is same if (s.Vaults.Count < minNeighbourVaults) { neighbourPrefix = p; minNeighbourVaults = (uint)s.Vaults.Count; smallestNeighbour = s; } else if (s.Vaults.Count == minNeighbourVaults) { // TODO tiebreaker for equal sized neighbours // see https://forum.safedev.org/t/data-chains-deeper-dive/1209 // If all neighbours have the same number of peers we relocate // to the section closest to the H above (that is not us) } } } } } // track neighbourhood hops by comparing how many bits differ // between the new and the old prefix. var neighbourhoodHops = 0; var prefixLength = smallestNeighbour.Prefix.Key.Length; if (ne.VaultToRelocate.Prefix.Key.Length < prefixLength) { prefixLength = ne.VaultToRelocate.Prefix.Key.Length; } for (int i = 0; i < prefixLength; i++) { var newBit = smallestNeighbour.Prefix.Key[i]; var oldBit = ne.VaultToRelocate.Prefix.Key[i]; if (newBit != oldBit) { neighbourhoodHops++; } } NeighbourhoodHops.Add(neighbourhoodHops); // remove vault from current section (includes merge if needed) RemoveVault(ne.VaultToRelocate); // adjust vault name to match the neighbour section prefix ne.VaultToRelocate.RenameWithPrefix(smallestNeighbour.Prefix); // age the relocated vault ne.VaultToRelocate.IncrementAge(); // relocate the vault to the smallest neighbour (includes split if needed) var disallowed = AddVault(ne.VaultToRelocate); if (disallowed) { Debug.WriteLine("Warning: disallowed relocated vault"); } }
public bool Equals(Prefix q) { return(Key == q.Key); }