From f5e0cc40840dc027e3b859a0ed66579d5e299a33 Mon Sep 17 00:00:00 2001 From: Alexandre Bourget Date: Wed, 23 May 2018 15:16:51 -0400 Subject: [PATCH] Mesh the boot node directly from t0. The BIOS Boot node should be behind a big firewall, with outgoing connections open, but incoming blocked. More input validation on `target_p2p_address`. Destroy accounts: do proper resignment of accounts, Removed the `hook_boot_connect_mesh.sh` as it now meshes from the start. --- bios/bios.go | 11 ++--- bios/discovery.go | 15 +++--- bios/hooks.go | 7 +-- bios/ops.go | 62 ++++++++++++++++++++----- files/boot_sequence.yaml | 14 ++---- sample_config/hook_boot_connect_mesh.sh | 21 --------- sample_config/hook_boot_node.sh | 3 ++ 7 files changed, 71 insertions(+), 62 deletions(-) delete mode 100755 sample_config/hook_boot_connect_mesh.sh diff --git a/bios/bios.go b/bios/bios.go index 529051a..b0ab51a 100644 --- a/bios/bios.go +++ b/bios/bios.go @@ -260,7 +260,9 @@ func (b *BIOS) RunBootSequence() error { } } - if err := b.DispatchBootNode(genesisData, pubKey.String(), privKey); err != nil { + orderedPeers := b.Network.OrderedPeers(b.Network.MyNetwork()) + otherPeers := b.someTopmostPeersAddresses(orderedPeers) + if err := b.DispatchBootNode(genesisData, pubKey.String(), privKey, otherPeers); err != nil { return fmt.Errorf("dispatch boot_node hook: %s", err) } @@ -324,13 +326,6 @@ func (b *BIOS) RunBootSequence() error { os.Exit(0) } - orderedPeers := b.Network.OrderedPeers(b.Network.MyNetwork()) - - otherPeers := b.someTopmostPeersAddresses(orderedPeers) - if err := b.DispatchBootConnectMesh(otherPeers); err != nil { - return fmt.Errorf("dispatch boot_connect_mesh: %s", err) - } - if err := b.DispatchBootPublishHandoff(); err != nil { return fmt.Errorf("dispatch boot_publish_handoff: %s", err) } diff --git a/bios/discovery.go b/bios/discovery.go index 0934704..140dd2e 100644 --- a/bios/discovery.go +++ b/bios/discovery.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io/ioutil" + "regexp" "strings" "github.com/eoscanada/eos-bios/bios/disco" @@ -33,6 +34,8 @@ func ValidateDiscoveryFile(filename string) error { return ValidateDiscovery(discovery) } +var p2pAddressRE = regexp.MustCompile(`[a-zA-Z0-9.:-]`) + func ValidateDiscovery(discovery *disco.Discovery) error { for _, peer := range discovery.SeedNetworkPeers { if peer.Weight > 100 || peer.Weight < 0 { @@ -52,16 +55,16 @@ func ValidateDiscovery(discovery *disco.Discovery) error { return errors.New("target_account_name should not contain '.'") } + if strings.Contains(discovery.TargetP2PAddress, "://") { + return fmt.Errorf("target_p2p_address should be of format ip:port, not prefixed with a protocol") + } + if !strings.Contains(discovery.TargetP2PAddress, ":") { return errors.New("target_p2p_address doesn't contain port number") } - // if strings.Contains(discovery.TargetP2PAddress, "example.com") { - // return errors.New("target_p2p_address contains an example.com domain, are you sure about that?") - // } - - if strings.Contains(discovery.TargetP2PAddress, "://") { - return fmt.Errorf("target_p2p_address should be of format ip:port, not prefixed with a protocol") + if !p2pAddressRE.MatchString(discovery.TargetP2PAddress) { + return errors.New("target_p2p_address is weird, should contain only [a-zA-Z0-9.:-]") } if !strings.Contains(discovery.TargetHTTPAddress, "://") { diff --git a/bios/hooks.go b/bios/hooks.go index ee70de7..7c149c5 100644 --- a/bios/hooks.go +++ b/bios/hooks.go @@ -24,16 +24,11 @@ func (b *BIOS) DispatchBootPublishGenesis(genesisJSON string) error { }, nil) } -func (b *BIOS) DispatchBootNode(genesisJSON, publicKey, privateKey string) error { +func (b *BIOS) DispatchBootNode(genesisJSON, publicKey, privateKey string, otherPeers []string) error { return b.dispatch("boot_node", []string{ genesisJSON, publicKey, privateKey, - }, nil) -} - -func (b *BIOS) DispatchBootConnectMesh(otherPeers []string) error { - return b.dispatch("boot_connect_mesh", []string{ "p2p-peer-address = " + strings.Join(otherPeers, "\np2p-peer-address = "), strings.Join(otherPeers, ","), }, nil) diff --git a/bios/ops.go b/bios/ops.go index b87733a..6b4e52c 100644 --- a/bios/ops.go +++ b/bios/ops.go @@ -458,34 +458,74 @@ func (op *OpDestroyAccounts) ResetTestnetOptions() { func (op *OpDestroyAccounts) Actions(b *BIOS) (out []*eos.Action, err error) { if op.TestnetKeepAccounts { - b.Log.Debugln("DEBUG: Keeping system account around, for testing purposes.") + b.Log.Debugln("DEBUG: Keeping system accounts around, for testing purposes.") return } - nullKey := ecc.PublicKey{Curve: ecc.CurveK1, Content: make([]byte, 33, 33)} + systemAccount := AN("eosio") + prodsAccount := AN("eosio.prods") // this is a special system account that is granted by 2/3 + 1 of the current BP schedule. + + //nullKey := ecc.PublicKey{Curve: ecc.CurveK1, Content: make([]byte, 33, 33)} for _, acct := range op.Accounts { + if acct == systemAccount { + continue // special treatment for `eosio` below + } out = append(out, system.NewUpdateAuth(acct, PN("active"), PN("owner"), eos.Authority{ Threshold: 1, - Keys: []eos.KeyWeight{ - { - PublicKey: nullKey, - Weight: 1, + Accounts: []eos.PermissionLevelWeight{ + eos.PermissionLevelWeight{ + Permission: eos.PermissionLevel{ + Actor: AN("eosio"), + Permission: PN("active"), + }, + Weight: 1, }, }, }, PN("active")), system.NewUpdateAuth(acct, PN("owner"), PN(""), eos.Authority{ Threshold: 1, - Keys: []eos.KeyWeight{ - { - PublicKey: nullKey, - Weight: 1, + Accounts: []eos.PermissionLevelWeight{ + eos.PermissionLevelWeight{ + Permission: eos.PermissionLevel{ + Actor: AN("eosio"), + Permission: PN("active"), + }, + Weight: 1, }, }, }, PN("owner")), nil, // end transaction ) - // unregister the producer at the same time ? } + + out = append(out, + system.NewUpdateAuth(systemAccount, PN("active"), PN("owner"), eos.Authority{ + Threshold: 1, + Accounts: []eos.PermissionLevelWeight{ + eos.PermissionLevelWeight{ + Permission: eos.PermissionLevel{ + Actor: prodsAccount, + Permission: PN("active"), + }, + Weight: 1, + }, + }, + }, PN("active")), + system.NewUpdateAuth(systemAccount, PN("owner"), PN(""), eos.Authority{ + Threshold: 1, + Accounts: []eos.PermissionLevelWeight{ + eos.PermissionLevelWeight{ + Permission: eos.PermissionLevel{ + Actor: prodsAccount, + Permission: PN("active"), + }, + Weight: 1, + }, + }, + }, PN("owner")), + nil, // end transaction + ) + return } diff --git a/files/boot_sequence.yaml b/files/boot_sequence.yaml index 092fb65..106b243 100644 --- a/files/boot_sequence.yaml +++ b/files/boot_sequence.yaml @@ -5,6 +5,9 @@ boot_sequence: account: eosio contract_name_ref: eosio.bios +- op: system.setprods + label: Setting the initial Appointed Block Producer schedule + - op: system.newaccount label: Create account b1 (to match `validate_b1_vesting` in system contract) data: @@ -122,20 +125,11 @@ boot_sequence: data: TESTNET_TRUNCATE_SNAPSHOT: 50 -- op: system.setprods - label: Setting the initial Appointed Block Producer schedule - -# - op: producers.register -# label: Register all producers with their declared key, URL and location - - op: system.destroy_accounts - label: Disabling authorization for system accounts + label: Disabling authorization for system accounts, pointing `eosio` to the `eosio.prods` system account. data: accounts: - #- eosio - eosio.msig - eosio.token - eosio.disco - eosio.unregd - -# TODO: also destroy the signing capability of `eosio`.. or `unregproducer` for `eosio`. \ No newline at end of file diff --git a/sample_config/hook_boot_connect_mesh.sh b/sample_config/hook_boot_connect_mesh.sh deleted file mode 100755 index d72ccc7..0000000 --- a/sample_config/hook_boot_connect_mesh.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -e - -# `boot_connect_mesh.sh` hook -# $1 p2p-peer-address statements (like the `join_network` hook) -# $2 comma-separated peer address list -# -# This hook is called when you 'eos-bios boot' or are seleted as BIOS -# Boot in an orchestrated launch. -# -# It should connect your boot node - -echo "Adding p2p-peer-address'es to config.ini" - -echo "$1" >> config.ini - - -echo "Restarting boot node" - -docker restart nodeos-bios - -sleep 2 diff --git a/sample_config/hook_boot_node.sh b/sample_config/hook_boot_node.sh index cc8c92c..8fa5b12 100755 --- a/sample_config/hook_boot_node.sh +++ b/sample_config/hook_boot_node.sh @@ -4,6 +4,8 @@ # $1 genesis JSON # $2 ephemeral public key # $3 ephemeral private key +# $4 = p2p_address_statements like "p2p-peer-address = 1.2.3.4\np2p-peer-address=2.3.4.5" +# $5 = p2p_addresses to connect to, split by comma # # This process must not BLOCK. @@ -16,6 +18,7 @@ echo $1 > genesis.json echo "producer-name = eosio" >> config.ini echo "enable-stale-production = true" >> config.ini echo "private-key = [\"$2\",\"$3\"]" >> config.ini +echo "$4" >> config.ini echo "Removing old nodeos data (you might be asked for your sudo password)..." sudo rm -rf /tmp/nodeos-data