beaconchain reset

pull/251/head
alok 6 years ago committed by ak
parent a8ed8546ca
commit 085a56bae7
  1. 16
      cmd/beaconchain/main.go
  2. 58
      internal/beaconchain/libs/beaconchain.go
  3. 31
      internal/beaconchain/libs/beaconchain_test.go
  4. 53
      internal/utils/utils.go

@ -27,7 +27,7 @@ func main() {
ip := flag.String("ip", "127.0.0.1", "ip on which beaconchain listens")
port := flag.String("port", "8081", "port on which beaconchain listens")
versionFlag := flag.Bool("version", false, "Output version info")
resetFlag := flag.String("path", "bc_config.json", "path to file")
flag.Parse()
if *versionFlag {
@ -36,9 +36,17 @@ func main() {
h := log.StdoutHandler
log.Root().SetHandler(h)
bc := beaconchain.New(*numShards, *ip, *port)
var bc *beaconchain.BeaconChain
if _, err := os.Stat(*resetFlag); err == nil {
bc, err = beaconchain.LoadBeaconChainInfo(*resetFlag)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not reset beaconchain from file: %+v\n", err)
}
} else {
fmt.Printf("Starting new beaconchain\n")
beaconchain.SetSaveFile(*resetFlag)
bc = beaconchain.New(*numShards, *ip, *port)
}
go bc.SupportRPC()
bc.StartServer()
}

@ -2,6 +2,7 @@ package beaconchain
import (
"math/rand"
"os"
"strconv"
"sync"
@ -27,11 +28,22 @@ var identityPerBlock = 100000
// BeaconchainServicePortDiff is the positive port diff from beacon chain's self port
const BeaconchainServicePortDiff = 4444
//BCInfo is the information that needs to be stored on the disk in order to allow for a restart.
type BCInfo struct {
Leaders []*bcconn.NodeInfo `json:"leaders"`
ShardLeaderMap map[int]*bcconn.NodeInfo `json:"shardleadermap"`
NumberOfShards int `json:"numshards"`
NumberOfNodesAdded int `json:"numnodesadded"`
IP string `json:"ip"`
Port string `json:"port"`
}
// BeaconChain (Blockchain) keeps Identities per epoch, currently centralized!
type BeaconChain struct {
Leaders []*bcconn.NodeInfo
log log.Logger
ShardLeaderMap map[int]*bcconn.NodeInfo
ShardNodeMap map[int]*bcconn.NodeInfo
PubKey kyber.Point
NumberOfShards int
NumberOfNodesAdded int
@ -39,9 +51,12 @@ type BeaconChain struct {
Port string
host host.Host
state BCState
saveFile string
rpcServer *beaconchain.Server
}
var SaveFile string
// Followings are the set of states of that beaconchain can be in.
const (
NodeInfoReceived BCState = iota
@ -104,10 +119,12 @@ func (bc *BeaconChain) AcceptNodeInfo(b []byte) *bcconn.NodeInfo {
Node := bcconn.DeserializeNodeInfo(b)
bc.log.Info("New Node Connection", "IP", Node.Self.IP, "Port", Node.Self.Port)
bc.NumberOfNodesAdded = bc.NumberOfNodesAdded + 1
_, isLeader := utils.AllocateShard(bc.NumberOfNodesAdded, bc.NumberOfShards)
shardNum, isLeader := utils.AllocateShard(bc.NumberOfNodesAdded, bc.NumberOfShards)
if isLeader {
bc.Leaders = append(bc.Leaders, Node)
bc.ShardLeaderMap[shardNum] = Node
}
go SaveBeaconChainInfo(SaveFile, bc)
bc.state = NodeInfoReceived
return Node
}
@ -132,3 +149,42 @@ func (bc *BeaconChain) AcceptConnections(b []byte) {
func (bc *BeaconChain) StartServer() {
bc.host.BindHandlerAndServe(bc.BeaconChainHandler)
}
//SaveBeaconChainInfo to disk
func SaveBeaconChainInfo(filePath string, bc *BeaconChain) error {
bci := BCtoBCI(bc)
err := utils.Save(filePath, bci)
return err
}
//LoadBeaconChainInfo from disk
func LoadBeaconChainInfo(path string) (*BeaconChain, error) {
bci := &BCInfo{}
var err error
if _, err := os.Stat(path); err != nil {
return nil, err
}
err = utils.Load(path, bci)
var bc *BeaconChain
if err != nil {
return nil, err
}
bc = BCItoBC(bci)
return bc, err
}
// BCtoBCI converts beaconchain into beaconchaininfo
func BCtoBCI(bc *BeaconChain) *BCInfo {
bci := &BCInfo{Leaders: bc.Leaders, ShardLeaderMap: bc.ShardLeaderMap, NumberOfShards: bc.NumberOfShards, NumberOfNodesAdded: bc.NumberOfNodesAdded, IP: bc.IP, Port: bc.Port}
return bci
}
//BCItoBC converts beconchaininfo to beaconchain
func BCItoBC(bci *BCInfo) *BeaconChain {
bc := &BeaconChain{Leaders: bci.Leaders, ShardLeaderMap: bci.ShardLeaderMap, NumberOfShards: bci.NumberOfShards, NumberOfNodesAdded: bci.NumberOfNodesAdded, IP: bci.IP, Port: bci.Port}
return bc
}
func SetSaveFile(path string) {
SaveFile = path
}

@ -1,6 +1,8 @@
package beaconchain
import (
"log"
"os"
"reflect"
"strconv"
"testing"
@ -110,3 +112,32 @@ func TestAcceptConnections(t *testing.T) {
bc.AcceptConnections(b)
assert.Equal(t, RandomInfoSent, bc.state)
}
func TestSaveBC(t *testing.T) {
var ip, port string
ip = "127.0.0.1"
port = "8080"
numshards := 2
bc := &BeaconChain{IP: ip, Port: port, NumberOfShards: numshards}
err := SaveBeaconChainInfo("test.json", bc)
if err != nil {
log.Fatalln(err)
}
bc2, err2 := LoadBeaconChainInfo("test.json")
if err2 != nil {
log.Fatalln(err2)
}
if !reflect.DeepEqual(bc, bc2) {
t.Error("beacon chain info objects are not same")
}
os.Remove("test.json")
}
func TestSaveFile(t *testing.T) {
filepath := "test"
SetSaveFile(filepath)
if !reflect.DeepEqual(filepath, SaveFile) {
t.Error("Could not set savefile")
}
}

@ -3,9 +3,13 @@ package utils
import (
"bytes"
"encoding/binary"
"encoding/json"
"io"
"log"
"os"
"regexp"
"strconv"
"sync"
"github.com/dedis/kyber"
"github.com/harmony-one/harmony/crypto"
@ -13,6 +17,24 @@ import (
"github.com/harmony-one/harmony/p2p"
)
var lock sync.Mutex
// Unmarshal is a function that unmarshals the data from the
// reader into the specified value.
func Unmarshal(r io.Reader, v interface{}) error {
return json.NewDecoder(r).Decode(v)
}
// Marshal is a function that marshals the object into an
// io.Reader.
func Marshal(v interface{}) (io.Reader, error) {
b, err := json.MarshalIndent(v, "", "\t")
if err != nil {
return nil, err
}
return bytes.NewReader(b), nil
}
// ConvertFixedDataIntoByteArray converts an empty interface data to a byte array
func ConvertFixedDataIntoByteArray(data interface{}) []byte {
buff := new(bytes.Buffer)
@ -66,3 +88,34 @@ func AllocateShard(numOfAddedNodes, numOfShards int) (int, bool) {
}
return numOfAddedNodes, true
}
// Save saves a representation of v to the file at path.
func Save(path string, v interface{}) error {
lock.Lock()
defer lock.Unlock()
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
r, err := Marshal(v)
if err != nil {
return err
}
_, err = io.Copy(f, r)
return err
}
// Load loads the file at path into v.
func Load(path string, v interface{}) error {
lock.Lock()
defer lock.Unlock()
f, err := os.Open(path)
if err != nil {
if os.IsNotExist(err) {
return err
}
}
defer f.Close()
return Unmarshal(f, v)
}

Loading…
Cancel
Save