Skip to content

Commit

Permalink
Network config; better finalization/rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
meyer9 committed May 31, 2019
1 parent c2968bc commit 3de2a84
Show file tree
Hide file tree
Showing 29 changed files with 23,104 additions and 693 deletions.
8 changes: 5 additions & 3 deletions beacon/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ import (
type Config struct {
RPCProto string
RPCAddress string
GenesisTime uint64
DataDirectory string
InitialValidatorList []beacon.InitialValidatorEntry
NetworkConfig *config.Config
Resync bool
IsIntegrationTest bool
Expand All @@ -34,8 +32,12 @@ type Config struct {
MinPeerCountToWait int
HeartBeatInterval time.Duration
TimeOutInterval time.Duration
DiscoveryOptions p2p.DiscoveryOptions
MaxPeers int

// These options are filled in through the chain file.
GenesisTime uint64
InitialValidatorList []beacon.InitialValidatorEntry
DiscoveryOptions p2p.DiscoveryOptions
}

// NewConfig creates a default Config
Expand Down
118 changes: 118 additions & 0 deletions beacon/app/networkfile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package app

import (
"encoding/hex"
"encoding/json"
"fmt"
"io"

peerstore "github.com/libp2p/go-libp2p-peerstore"
multiaddr "github.com/multiformats/go-multiaddr"
"github.com/phoreproject/synapse/beacon/config"
"github.com/phoreproject/synapse/p2p"

"github.com/phoreproject/synapse/beacon"
)

// InitialValidatorInformation is the encoded information from the JSON file of an
// initial validator.
type InitialValidatorInformation struct {
PubKey string
ProofOfPossession string
WithdrawalShard uint32
WithdrawalCredentials string
DepositSize uint64
ID uint32
}

// InitialValidatorList is a list of initial validators and the number of validators
type InitialValidatorList struct {
NumValidators int
Validators []InitialValidatorInformation
}

// ChainConfig is the JSON encoded information about the network.
type ChainConfig struct {
GenesisTime uint64
BootstrapPeers []string
NetworkID string
InitialValidators InitialValidatorList
}

// GenerateConfigFromChainConfig generates a new config from the passed in network config
// which should be loaded from a JSON file.
func GenerateConfigFromChainConfig(chainConfig ChainConfig) (*Config, error) {
c := NewConfig()

c.InitialValidatorList = make([]beacon.InitialValidatorEntry, chainConfig.InitialValidators.NumValidators)
for i := range c.InitialValidatorList {
validator := chainConfig.InitialValidators.Validators[i]

pubKeyBytes, err := hex.DecodeString(validator.PubKey)
if err != nil {
return nil, err
}
var pubKey [96]byte
copy(pubKey[:], pubKeyBytes)

sigBytes, err := hex.DecodeString(validator.ProofOfPossession)
if err != nil {
return nil, err
}
var signature [48]byte
copy(signature[:], sigBytes)

withdrawalCredentialsBytes, err := hex.DecodeString(validator.WithdrawalCredentials)
if err != nil {
return nil, err
}
var withdrawalCredentials [32]byte
copy(withdrawalCredentials[:], withdrawalCredentialsBytes)

c.InitialValidatorList[i] = beacon.InitialValidatorEntry{
PubKey: pubKey,
ProofOfPossession: signature,
WithdrawalCredentials: withdrawalCredentials,
WithdrawalShard: validator.WithdrawalShard,
DepositSize: validator.DepositSize,
}
}

c.GenesisTime = chainConfig.GenesisTime

c.DiscoveryOptions = p2p.NewDiscoveryOptions()
c.DiscoveryOptions.PeerAddresses = make([]peerstore.PeerInfo, len(chainConfig.BootstrapPeers))

networkConfig, found := config.NetworkIDs[chainConfig.NetworkID]
if !found {
return nil, fmt.Errorf("error getting network config for ID: %s", chainConfig.NetworkID)
}
c.NetworkConfig = &networkConfig

for i := range c.DiscoveryOptions.PeerAddresses {
a, err := multiaddr.NewMultiaddr(chainConfig.BootstrapPeers[i])
if err != nil {
return nil, err
}
peerInfo, err := peerstore.InfoFromP2pAddr(a)
if err != nil {
return nil, err
}
c.DiscoveryOptions.PeerAddresses[i] = *peerInfo
}

return &c, nil
}

// ReadChainFileToConfig reads a network config from the reader.
func ReadChainFileToConfig(r io.Reader) (*Config, error) {
var networkConfig ChainConfig

d := json.NewDecoder(r)
err := d.Decode(&networkConfig)
if err != nil {
return nil, err
}

return GenerateConfigFromChainConfig(networkConfig)
}
27 changes: 14 additions & 13 deletions beacon/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,17 @@ func NewBlockchainWithInitialValidators(db db.Database, config *config.Config, v
View: NewBlockchainView(),
}

sm, err := NewStateManager(config, validators, genesisTime, skipValidation, b, db)
sm, err := NewStateManager(config, genesisTime, b, db)
if err != nil {
return nil, err
}

b.stateManager = sm

initialState := sm.GetHeadState()
initialState, err := InitializeState(config, validators, genesisTime, skipValidation)
if err != nil {
return nil, err
}

stateRoot, err := ssz.TreeHash(initialState)
if err != nil {
Expand Down Expand Up @@ -142,27 +145,27 @@ func NewBlockchainWithInitialValidators(db db.Database, config *config.Config, v
if err != nil {
b.View.Chain.SetTip(node)

b.View.SetFinalizedHead(blockHash, initialState)
b.View.SetJustifiedHead(blockHash, initialState)
b.View.SetFinalizedHead(blockHash, *initialState)
b.View.SetJustifiedHead(blockHash, *initialState)
err = b.DB.SetJustifiedHead(node.Hash)
if err != nil {
return nil, err
}
err = b.DB.SetJustifiedState(initialState)
err = b.DB.SetJustifiedState(*initialState)
if err != nil {
return nil, err
}
err = b.DB.SetFinalizedHead(node.Hash)
if err != nil {
return nil, err
}
err = b.DB.SetFinalizedState(initialState)
err = b.DB.SetFinalizedState(*initialState)
if err != nil {
return nil, err
}
b.View.Chain.SetTip(node)

err = b.stateManager.SetBlockState(blockHash, &initialState)
err = b.stateManager.SetBlockState(blockHash, initialState)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -198,23 +201,21 @@ func NewBlockchainWithInitialValidators(db db.Database, config *config.Config, v
func (b *Blockchain) GetUpdatedState(upTo uint64) (*primitives.State, error) {
tip := b.View.Chain.Tip()

tipState := b.stateManager.GetHeadState()

tipStateCopy := tipState.Copy()

view := NewChainView(tip)

err := tipStateCopy.ProcessSlots(upTo, &view, b.config)
tipState, err := b.stateManager.GetStateForHashAtSlot(tip.Hash, upTo, &view, b.config)
if err != nil {
return nil, err
}

tipStateCopy := tipState.Copy()

return &tipStateCopy, nil
}

// GetNextSlotTime returns the timestamp of the next slot.
func (b *Blockchain) GetNextSlotTime() time.Time {
return time.Unix(int64((b.stateManager.GetHeadSlot()+1)*uint64(b.config.SlotDuration)+b.stateManager.GetGenesisTime()), 0)
return time.Unix(int64((b.View.Chain.Tip().Slot+1)*uint64(b.config.SlotDuration)+b.stateManager.GetGenesisTime()), 0)
}

// InitialValidatorEntry is the validator entry to be added
Expand Down
41 changes: 39 additions & 2 deletions beacon/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ var MainNetConfig = Config{
LatestBlockRootsLength: 8192,
InitialForkVersion: 0,
InitialSlotNumber: 0,
SlotDuration: 4,
EpochLength: 64,
SlotDuration: 7,
EpochLength: 32,
MinAttestationInclusionDelay: 4,
CollectivePenaltyCalculationPeriod: 1048576,
ZeroBalanceValidatorTTL: 4194304,
Expand All @@ -64,6 +64,36 @@ var MainNetConfig = Config{
MinDeposit: 2 * UnitInCoin,
}

// LocalnetConfig is the config used for testing the blockchain locally
var LocalnetConfig = Config{
ShardCount: 32,
TargetCommitteeSize: 4,
EjectionBalance: 16,
MaxBalanceChurnQuotient: 32,
BeaconShardNumber: 18446744073709551615,
BLSWithdrawalPrefixByte: '\x00',
MaxCasperVotes: 1024,
LatestBlockRootsLength: 8192,
InitialForkVersion: 0,
InitialSlotNumber: 0,
SlotDuration: 4,
EpochLength: 8,
MinAttestationInclusionDelay: 2,
CollectivePenaltyCalculationPeriod: 1048576,
ZeroBalanceValidatorTTL: 4194304,
BaseRewardQuotient: 1024,
WhistleblowerRewardQuotient: 512,
IncluderRewardQuotient: 8,
InactivityPenaltyQuotient: 17179869184,
MaxProposerSlashings: 16,
MaxCasperSlashings: 16,
MaxAttestations: 128,
MaxDeposits: 16,
MaxExits: 16,
MaxDeposit: 64 * UnitInCoin,
MinDeposit: 2 * UnitInCoin,
}

// RegtestConfig is the config used for unit tests
var RegtestConfig = Config{
ShardCount: 4,
Expand Down Expand Up @@ -93,3 +123,10 @@ var RegtestConfig = Config{
MaxDeposit: 64 * UnitInCoin,
MinDeposit: 2 * UnitInCoin,
}

// NetworkIDs maps a network ID string to the corresponding config.
var NetworkIDs = map[string]Config{
"localnet": LocalnetConfig,
"regtest": RegtestConfig,
"testnet": MainNetConfig,
}
5 changes: 0 additions & 5 deletions beacon/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,6 @@ func (b *Blockchain) populateStateMap() error {

b.View.Chain.SetTip(finalizedNode)

err = b.stateManager.UpdateHead(finalizedNode.Hash)
if err != nil {
return err
}

for len(loadQueue) > 0 {
itemToLoad := loadQueue[0]

Expand Down
6 changes: 1 addition & 5 deletions beacon/ghost.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,8 @@ func (b *Blockchain) UpdateChainHead() error {
children := head.Children
if len(children) == 0 {
b.View.Chain.SetTip(head)
err := b.stateManager.UpdateHead(head.Hash)
if err != nil {
return err
}

err = b.DB.SetHeadBlock(head.Hash)
err := b.DB.SetHeadBlock(head.Hash)
if err != nil {
return err
}
Expand Down
14 changes: 4 additions & 10 deletions beacon/mempool.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package beacon

import (
"errors"
"sort"
"sync"

Expand Down Expand Up @@ -54,28 +53,23 @@ func newAttestationMempool() *attestationMempool {
func (m *Mempool) ProcessNewAttestation(att primitives.Attestation) error {
// first, validate the attestation
tipHash := m.blockchain.View.Chain.Tip().Hash
tipState, found := m.blockchain.stateManager.GetStateForHash(tipHash)
if !found {
return errors.New("no state for blockchain tip")
}

tipView, err := m.blockchain.GetSubView(tipHash)
if err != nil {
return err
}

stateCopy := tipState.Copy()

firstSlotAttestationCouldBeIncluded := att.Data.Slot + m.blockchain.config.MinAttestationInclusionDelay

err = stateCopy.ProcessSlots(firstSlotAttestationCouldBeIncluded, &tipView, m.blockchain.config)
tipState, err := m.blockchain.stateManager.GetStateForHashAtSlot(tipHash, firstSlotAttestationCouldBeIncluded, &tipView, m.blockchain.config)
if err != nil {
return err
}

tipView.SetTipSlot(firstSlotAttestationCouldBeIncluded)

// this assumes the state will be the same at att.Data.Slot
err = stateCopy.ValidateAttestation(att, true, &tipView, m.blockchain.config, firstSlotAttestationCouldBeIncluded)
// if the first slot it could be included is
err = tipState.ValidateAttestation(att, true, &tipView, m.blockchain.config, tipState.Slot-1)
if err != nil {
return err
}
Expand Down
16 changes: 13 additions & 3 deletions beacon/rpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
package rpc

import (
"fmt"
"net"

"github.com/sirupsen/logrus"

"github.com/phoreproject/synapse/p2p"
"github.com/phoreproject/synapse/utils"

Expand Down Expand Up @@ -86,7 +85,6 @@ func (s *server) SubmitBlock(ctx context.Context, in *pb.SubmitBlockRequest) (*p
return nil, err
}

logrus.Debug("broadcasting")
err = s.p2p.Broadcast("block", data)
if err != nil {
return nil, err
Expand Down Expand Up @@ -264,6 +262,18 @@ func (s *server) GetBlock(ctx context.Context, in *pb.GetBlockRequest) (*pb.GetB
}, nil
}

func (s *server) GetValidatorInformation(ctx context.Context, in *pb.GetValidatorRequest) (*pb.Validator, error) {
state := s.chain.GetState()

if uint32(len(state.ValidatorRegistry)) <= in.ID {
return nil, fmt.Errorf("could not find validator with ID %d", in.ID)
}

validator := state.ValidatorRegistry[in.ID]

return validator.ToProto(), nil
}

// Serve serves the RPC server
func Serve(proto string, listenAddr string, b *beacon.Blockchain, hostNode *p2p.HostNode, mempool *beacon.Mempool) error {
lis, err := net.Listen(proto, listenAddr)
Expand Down
Loading

0 comments on commit 3de2a84

Please sign in to comment.