예제 #1
0
        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);
        }
예제 #2
0
        // @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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        // 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);
        }
예제 #8
0
        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);
        }
예제 #9
0
 int AdultCountForExtendedPrefix(Prefix p)
 {
     return(Vaults.Count(v => v.IsAdult() && p.Matches(v.Name)));
 }
예제 #10
0
        int RightAdultCount()
        {
            var rightPrefix = Prefix.ExtendRight();

            return(AdultCountForExtendedPrefix(rightPrefix));
        }
예제 #11
0
        int LeftAdultCount()
        {
            var leftPrefix = Prefix.ExtendLeft();

            return(AdultCountForExtendedPrefix(leftPrefix));
        }
예제 #12
0
 int VaultCountForExtendedPrefix(Prefix p)
 {
     return(Vaults.Count(v => p.Matches(v.Name)));
 }
예제 #13
0
 public void SetPrefix(Prefix p)
 {
     Prefix = p;
 }
예제 #14
0
        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");
            }
        }
예제 #15
0
 public bool Equals(Prefix q)
 {
     return(Key == q.Key);
 }