コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        // 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);
        }
コード例 #4
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);
        }
コード例 #5
0
        int LeftAdultCount()
        {
            var leftPrefix = Prefix.ExtendLeft();

            return(AdultCountForExtendedPrefix(leftPrefix));
        }
コード例 #6
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");
            }
        }