NetworkEvent Split() { var leftPrefix = Prefix.ExtendLeft(); var rightPrefix = Prefix.ExtendRight(); var left = new List <Vault>(); var right = new List <Vault>(); foreach (var v in Vaults) { if (leftPrefix.Matches(v.Name)) { left.Add(v); } else if (rightPrefix.Matches(v.Name)) { right.Add(v); } else { Debug.WriteLine("Warning: Split has vault that doesn't match extended prefix"); } } var ne0 = NewSection(leftPrefix, left); var ne1 = NewSection(rightPrefix, right); var ne = new NetworkEvent { NewSections = ne0.NewSections.Concat(ne1.NewSections).ToList() }; return(ne); }
List <Prefix> GetChildPrefixes(Prefix prefix) { var prefixes = new List <Prefix>(); var leftPrefix = prefix.ExtendLeft(); var rightPrefix = prefix.ExtendRight(); var leftExists = Sections.ContainsKey(leftPrefix.Key); var rightExists = Sections.ContainsKey(rightPrefix.Key); if (leftExists && rightExists) { prefixes.AddRange(new[] { leftPrefix, rightPrefix }); } else if (leftExists) { prefixes.Add(leftPrefix); prefixes.AddRange(GetChildPrefixes(rightPrefix)); } else if (rightExists) { prefixes.Add(rightPrefix); prefixes.AddRange(GetChildPrefixes(leftPrefix)); } else if (prefix.Bits.Count < 256) { prefixes.AddRange(GetChildPrefixes(leftPrefix)); prefixes.AddRange(GetChildPrefixes(rightPrefix)); } else { Debug.WriteLine("Warning: No children exist for prefix"); } return(prefixes); }
// Returns the parent, prefix, or children that matches this prefix on the network public List <Prefix> GetMatchingPrefixes(Prefix prefix) { var prefixes = new List <Prefix>(); var testPrefix = new Prefix(); // find possible parents if (Sections.ContainsKey(testPrefix.Key)) { prefixes.Add(testPrefix); } for (int i = 0; i < prefix.Bits.Count; i++) { if (!prefix.Bits[i]) { testPrefix = testPrefix.ExtendLeft(); } else { testPrefix = testPrefix.ExtendRight(); } if (Sections.ContainsKey(testPrefix.Key)) { prefixes.Add(testPrefix); // TODO can probably break here? } } // get child prefixes if no parent found if (prefixes.Count == 0) { prefixes = GetChildPrefixes(prefix); } return(prefixes); }
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 LeftAdultCount() { var leftPrefix = Prefix.ExtendLeft(); return(AdultCountForExtendedPrefix(leftPrefix)); }
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"); } }