diff --git a/bios/bios.go b/bios/bios.go index 1bb8234..1b48a87 100644 --- a/bios/bios.go +++ b/bios/bios.go @@ -835,7 +835,7 @@ func (b *BIOS) shuffleProducers() { b.Log.Println("Shuffling producers listed in the launch file") r := rand.New(b.RandSource) // shuffle top 25%, capped to 5 - shuffleHowMany := int64(math.Min(math.Ceil(float64(len(b.ShuffledProducers))*0.25), 5)) + shuffleHowMany := int64(math.Min(math.Ceil(float64(len(b.ShuffledProducers))*0.25), RandomBootFromTop)) if shuffleHowMany > 1 { b.Log.Println("- Shuffling top", shuffleHowMany) for round := 0; round < 100; round++ { diff --git a/bios/network.go b/bios/network.go index ebccb01..54ae3fa 100644 --- a/bios/network.go +++ b/bios/network.go @@ -20,7 +20,8 @@ import ( "gonum.org/v1/gonum/graph/topo" ) -const ContentConsensusRequiredFromTop = 7 +const ContentConsensusRequiredFromTop = 8 +const RandomBootFromTop = 5 type Network struct { Log *Logger @@ -383,12 +384,32 @@ func (net *Network) OrderedPeers(network *simple.WeightedDirectedGraph) (out []* if out[i].TotalWeight == out[j].TotalWeight { return out[i].AccountName() < out[j].AccountName() } + return out[i].TotalWeight > out[j].TotalWeight }) + out = bootOptInFilter(out) + return } +func bootOptInFilter(in []*Peer) (out []*Peer) { + var launchers []*Peer + var nonLaunchers []*Peer + for _, el := range in { + if el.Discovery.SeedNetworkLaunchBlock == 0 { + nonLaunchers = append(nonLaunchers, el) + } else { + launchers = append(launchers, el) + } + } + maxLaunchers := RandomBootFromTop + if len(launchers) < RandomBootFromTop { + maxLaunchers = len(launchers) + } + return append(launchers[:maxLaunchers], append(nonLaunchers, launchers[maxLaunchers:]...)...) +} + func (net *Network) GetBlockHeight(height uint32) (eos.SHA256Bytes, error) { resp, err := net.SeedNetAPI.GetBlockByNum(height) if err != nil { @@ -521,12 +542,14 @@ func (net *Network) PrintOrderedPeers(orderedPeers []*Peer) { "Role | Seed Account | Target Acct | Weight | GMT | Launch Block | Contents", "---- | ------------ | ----------- | ------ | --- | ------------ | --------", } - columns = append(columns, fmt.Sprintf("BIOS NODE | %s | %s", orderedPeers[0].Columns(), peerContent[0])) - for i := 1; i < 22 && len(orderedPeers) > i; i++ { - columns = append(columns, fmt.Sprintf("ABP %02d | %s | %s", i, orderedPeers[i].Columns(), peerContent[i])) + for i := 0; i < RandomBootFromTop && len(orderedPeers) > i; i++ { + columns = append(columns, fmt.Sprintf("BOOT CAND. | %s | %s", orderedPeers[i].Columns(), peerContent[i])) + } + for i := RandomBootFromTop; i < 21 && len(orderedPeers) > i; i++ { + columns = append(columns, fmt.Sprintf("ABP %02d | %s | %s", i+1, orderedPeers[i].Columns(), peerContent[i])) } - for i := 22; len(orderedPeers) > i; i++ { - columns = append(columns, fmt.Sprintf("Part. %02d | %s | %s", i, orderedPeers[i].Columns(), peerContent[i])) + for i := 21; len(orderedPeers) > i; i++ { + columns = append(columns, fmt.Sprintf("Part. %02d | %s | %s", i+1, orderedPeers[i].Columns(), peerContent[i])) } net.Log.Println(columnize.SimpleFormat(columns)) diff --git a/bios/network_test.go b/bios/network_test.go new file mode 100644 index 0000000..a91c517 --- /dev/null +++ b/bios/network_test.go @@ -0,0 +1,48 @@ +package bios + +import ( + "testing" + + "github.com/eoscanada/eos-bios/bios/disco" + "github.com/stretchr/testify/assert" +) + +func TestBootOptInFilter(t *testing.T) { + tests := []struct { + in string + out string + }{ + {"ABcDeFGhIJ", "ABDFGcehIJ"}, + {"ABCDEFGHIJ", "ABCDEFGHIJ"}, + {"abcdeFGHIJ", "FGHIJabcde"}, + {"abcdefGHIJ", "GHIJabcdef"}, + {"abcdefGHIJKLM", "GHIJKabcdefLM"}, + {"abcdefghIJ", "IJabcdefgh"}, + {"abcde", "abcde"}, + {"abC", "Cab"}, + {"abcdeF", "Fabcde"}, + {"abcdeFGHI", "FGHIabcde"}, + } + + for _, test := range tests { + in := bootFilterPeers(test.in) + out := bootFilterPeers(test.out) + + assert.Equal(t, out, bootOptInFilter(in)) + } +} + +func bootFilterPeers(in string) []*Peer { + var out []*Peer + for _, c := range in { + block := 0 + if c < 92 { + block = 1 + } + out = append(out, &Peer{Discovery: &disco.Discovery{ + SeedNetworkAccountName: AN(string(c)), + SeedNetworkLaunchBlock: uint64(block), + }}) + } + return out +} diff --git a/bios/peer.go b/bios/peer.go index 79a9853..1d93c56 100644 --- a/bios/peer.go +++ b/bios/peer.go @@ -52,11 +52,18 @@ func (p *Peer) String() string { } func (p *Peer) Columns() string { - active := "" + add := "" if p.Active() { - active = "A " + add += "A" + if p.Discovery.SeedNetworkLaunchBlock != 0 { + add += "B" + } } - return fmt.Sprintf("%s | %s | %s%d | %d | %d", p.Discovery.SeedNetworkAccountName, p.Discovery.TargetAccountName, active, p.TotalWeight, p.Discovery.GMTOffset, p.Discovery.SeedNetworkLaunchBlock) + if len(add) != 0 { + add += " " + } + + return fmt.Sprintf("%s | %s | %s%d | %d | %d", p.Discovery.SeedNetworkAccountName, p.Discovery.TargetAccountName, add, p.TotalWeight, p.Discovery.GMTOffset, p.Discovery.SeedNetworkLaunchBlock) } // PeerEdge is an internal structure that links two Discovery peers. diff --git a/sample_config/my_discovery_file.yaml b/sample_config/my_discovery_file.yaml index 6b372e2..0bd9900 100644 --- a/sample_config/my_discovery_file.yaml +++ b/sample_config/my_discovery_file.yaml @@ -16,7 +16,10 @@ seed_network_peers: comment: "Insert why you think they're worth that weight" weight: 20 -seed_network_launch_block: 551 # Block on the SEED EOS network before we orchestrate the TARGET network launch. Putting a past block will start orchestration right away. +# Block on the SEED EOS network before we orchestrate the TARGET network launch. +# Putting a past block will start orchestration right away. +# Setting it 0 means you OPT OUT of being selected the BIOS Boot node. +seed_network_launch_block: 0 urls: - https://website.com