示例#1
0
func Factomd() {

	log.Print("//////////////////////// Copyright 2015 Factom Foundation")
	log.Print("//////////////////////// Use of this source code is governed by the MIT")
	log.Print("//////////////////////// license that can be found in the LICENSE file.")
	log.Printf("Go compiler version: %s\n", runtime.Version())
	log.Printf("Using build: %s\n", Build)

	if !isCompilerVersionOK() {
		for i := 0; i < 30; i++ {
			log.Println("!!! !!! !!! ERROR: unsupported compiler version !!! !!! !!!")
		}
		time.Sleep(3 * time.Second)
		os.Exit(1)
	}

	//  Go Optimizations...
	runtime.GOMAXPROCS(runtime.NumCPU())

	state0 := new(state.State)
	state0.SetLeaderTimestamp(primitives.NewTimestampFromMilliseconds(0))
	fmt.Println("len(Args)", len(os.Args))

	NetStart(state0)
}
示例#2
0
func newEOM() *EOM {
	eom := new(EOM)
	eom.Timestamp = primitives.NewTimestampFromMilliseconds(0xFF22100122FF)
	eom.Minute = 3
	h, err := primitives.NewShaHashFromStr("deadbeef00000000000000000000000000000000000000000000000000000000")
	if err != nil {
		panic(err)
	}
	eom.ChainID = h
	eom.DBHeight = 123456

	return eom
}
示例#3
0
func Test_Replay(test *testing.T) {

	type mh struct {
		hash [32]byte
		time interfaces.Timestamp
	}

	go func() {
		log.Println(http.ListenAndServe("localhost:6060", nil))
	}()

	XTrans := 61440 //102400000 //61440 //145000

	var mhs []*mh

	start := primitives.NewTimestampNow()
	now := primitives.NewTimestampNow()

	for i := 0; i < XTrans; i++ {

		if (i+1)%1000 == 0 {

			buckets := len(r.Buckets)
			bcnt := 0
			for _, b := range r.Buckets {
				bcnt += len(b)
			}
			secs := now.GetTimeSeconds() - start.GetTimeSeconds()
			fmt.Printf("Test in %d minute, %d buckets, %d elements, %d center\n", Minutes(secs), buckets, bcnt, r.Center)
			// Now replay all the transactions we have collected.  NONE of them
			// should work.

			for in := 0; in < 1000; in++ {
				i := rand.Int() % len(mhs)
				x := mhs[i]
				if r.IsTSValid_(constants.INTERNAL_REPLAY, x.hash, x.time, now) {
					fmt.Printf("Failed Repeat Test %d\n", i)
					test.Fail()
					return
				}
			}
			time.Sleep(10 * time.Millisecond)
		}

		if (i+1)%10000 == 0 {
			mhs = mhs[:0]
		}

		// We are going to remember some large set of transactions.
		x := new(mh)
		x.hash = primitives.Sha([]byte(fmt.Sprintf("h%d", i))).Fixed()
		mhs = append(mhs, x)

		// Build a valid transaction somewhere +/- span hours of now
		delta := int64(float32(spanMin*2) * rand.Float32())
		ntime := now.GetTimeSeconds()/60 - spanMin + delta
		x.time = primitives.NewTimestampFromSeconds(uint32(ntime * 60))

		if _, ok := r.Valid(constants.INTERNAL_REPLAY, x.hash, x.time, now); !ok {
			mnow := Minutes(now.GetTimeSeconds())
			mx := Minutes(x.time.GetTimeSeconds())
			fmt.Printf("Failed an element in the time range. Test %d element Time: %d now %d Diff %d\n", i, mx, mnow, mx-mnow)
			test.Fail()
			return
		}

		// The first time we test, it should be valid.
		if !r.IsTSValid_(constants.INTERNAL_REPLAY, x.hash, x.time, now) {
			fmt.Println("Failed Test ", i, "first")
			test.Fail()
			return
		}

		// An immediate replay!  Should fail!
		if r.IsTSValid_(constants.INTERNAL_REPLAY, x.hash, x.time, now) {
			fmt.Println("Failed Test ", i, "second")
			test.Fail()
			return
		}

		x = new(mh)
		x.hash = primitives.Sha([]byte(fmt.Sprintf("xh%d", i))).Fixed()

		// Build a invalid transaction > span in the past
		delta = now.GetTimeSeconds()/60 - spanMin + 1 + rand.Int63()%20
		ntime = now.GetTimeSeconds()/60 - delta
		x.time = primitives.NewTimestampFromSeconds(uint32(ntime * 60))

		// should not be valid
		if _, ok := r.Valid(constants.INTERNAL_REPLAY, x.hash, x.time, now); ok {
			mnow := Minutes(now.GetTimeSeconds())
			mx := Minutes(x.time.GetTimeSeconds())
			fmt.Printf("Okayed an element out of time range. Test %d element Time: %d now %d Diff %d\n", i, mx, mnow, mx-mnow)
			test.Fail()
			return
		}

		// The first time we test, it should not be valid.
		if r.IsTSValid_(constants.INTERNAL_REPLAY, x.hash, x.time, now) {
			fmt.Println("Failed Test ", i, "bad first")
			test.Fail()
			return
		}

		// Move time forward somewhere between 0 to 15 minutes
		now = primitives.NewTimestampFromMilliseconds(uint64(now.GetTimeMilli() + rand.Int63()%(speed)))

	}

	fmt.Println("Simulation ran from", time.Unix(start.GetTimeSeconds(), 0), "to", time.Unix(now.GetTimeSeconds(), 0))

}
示例#4
0
func NetStart(s *state.State) {
	enablenetPtr := flag.Bool("enablenet", true, "Enable or disable networking")
	listenToPtr := flag.Int("node", 0, "Node Number the simulator will set as the focus")
	cntPtr := flag.Int("count", 1, "The number of nodes to generate")
	netPtr := flag.String("net", "tree", "The default algorithm to build the network connections")
	fnetPtr := flag.String("fnet", "", "Read the given file to build the network connections")
	dropPtr := flag.Int("drop", 0, "Number of messages to drop out of every thousand")
	journalPtr := flag.String("journal", "", "Rerun a Journal of messages")
	journalingPtr := flag.Bool("journaling", false, "Write a journal of all messages recieved. Default is off.")
	followerPtr := flag.Bool("follower", false, "If true, force node to be a follower.  Only used when replaying a journal.")
	leaderPtr := flag.Bool("leader", true, "If true, force node to be a leader.  Only used when replaying a journal.")
	dbPtr := flag.String("db", "", "Override the Database in the Config file and use this Database implementation")
	cloneDBPtr := flag.String("clonedb", "", "Override the main node and use this database for the clones in a Network.")
	portOverridePtr := flag.Int("port", 0, "Address to serve WSAPI on")
	networkNamePtr := flag.String("network", "", "Network to join: MAIN, TEST or LOCAL")
	networkPortOverridePtr := flag.Int("networkPort", 0, "Address for p2p network to listen on.")
	peersPtr := flag.String("peers", "", "Array of peer addresses. ")
	blkTimePtr := flag.Int("blktime", 0, "Seconds per block.  Production is 600.")
	runtimeLogPtr := flag.Bool("runtimeLog", false, "If true, maintain runtime logs of messages passed.")
	netdebugPtr := flag.Int("netdebug", 0, "0-5: 0 = quiet, >0 = increasing levels of logging")
	exclusivePtr := flag.Bool("exclusive", false, "If true, we only dial out to special/trusted peers.")
	prefixNodePtr := flag.String("prefix", "", "Prefix the Factom Node Names with this value; used to create leaderless networks.")
	rotatePtr := flag.Bool("rotate", false, "If true, responsiblity is owned by one leader, and rotated over the leaders.")
	timeOffsetPtr := flag.Int("timedelta", 0, "Maximum timeDelta in milliseconds to offset each node.  Simulates deltas in system clocks over a network.")
	keepMismatchPtr := flag.Bool("keepmismatch", false, "If true, do not discard DBStates even when a majority of DBSignatures have a different hash")
	startDelayPtr := flag.Int("startdelay", 10, "Delay to start processing messages, in seconds")
	deadlinePtr := flag.Int("deadline", 1000, "Timeout Delay in milliseconds used on Reads and Writes to the network comm")
	customNetPtr := flag.String("customnet", "", "This string specifies a custom blockchain network ID.")
	rpcUserflag := flag.String("rpcuser", "", "Username to protect factomd local API with simple HTTP authentication")
	rpcPasswordflag := flag.String("rpcpass", "", "Password to protect factomd local API. Ignored if rpcuser is blank")
	factomdTLSflag := flag.Bool("tls", false, "Set to true to require encrypted connections to factomd API and Control Panel") //to get tls, run as "factomd -tls=true"
	factomdLocationsflag := flag.String("selfaddr", "", "comma seperated IPAddresses and DNS names of this factomd to use when creating a cert file")

	flag.Parse()

	enableNet := *enablenetPtr
	listenTo := *listenToPtr
	cnt := *cntPtr
	net := *netPtr
	fnet := *fnetPtr
	droprate := *dropPtr
	journal := *journalPtr
	journaling := *journalingPtr
	follower := *followerPtr
	leader := *leaderPtr
	db := *dbPtr
	cloneDB := *cloneDBPtr
	portOverride := *portOverridePtr
	peers := *peersPtr
	networkName := *networkNamePtr
	networkPortOverride := *networkPortOverridePtr
	blkTime := *blkTimePtr
	runtimeLog := *runtimeLogPtr
	netdebug := *netdebugPtr
	exclusive := *exclusivePtr
	prefix := *prefixNodePtr
	rotate := *rotatePtr
	timeOffset := *timeOffsetPtr
	keepMismatch := *keepMismatchPtr
	startDelay := int64(*startDelayPtr)
	deadline := *deadlinePtr
	customNet := primitives.Sha([]byte(*customNetPtr)).Bytes()[:4]
	rpcUser := *rpcUserflag
	rpcPassword := *rpcPasswordflag
	factomdTLS := *factomdTLSflag
	factomdLocations := *factomdLocationsflag

	// Must add the prefix before loading the configuration.
	s.AddPrefix(prefix)
	FactomConfigFilename := util.GetConfigFilename("m2")
	fmt.Println(fmt.Sprintf("factom config: %s", FactomConfigFilename))
	s.LoadConfig(FactomConfigFilename, networkName)
	s.OneLeader = rotate
	s.TimeOffset = primitives.NewTimestampFromMilliseconds(uint64(timeOffset))
	s.StartDelayLimit = startDelay * 1000
	s.Journaling = journaling

	if 999 < portOverride { // The command line flag exists and seems reasonable.
		s.SetPort(portOverride)
	}

	if blkTime != 0 {
		s.DirectoryBlockInSeconds = blkTime
	} else {
		blkTime = s.DirectoryBlockInSeconds
	}

	if follower {
		leader = false
	}
	if leader {
		follower = false
	}
	if !follower && !leader {
		panic("Not a leader or a follower")
	}

	if journal != "" {
		cnt = 1
	}

	if rpcUser != "" {
		s.RpcUser = rpcUser
	}

	if rpcPassword != "" {
		s.RpcPass = rpcPassword
	}

	if factomdTLS == true {
		s.FactomdTLSEnable = true
	}

	if factomdLocations != "" {
		if len(s.FactomdLocations) > 0 {
			s.FactomdLocations += ","
		}
		s.FactomdLocations += factomdLocations
	}

	fmt.Println(">>>>>>>>>>>>>>>>")
	fmt.Println(">>>>>>>>>>>>>>>> Net Sim Start!")
	fmt.Println(">>>>>>>>>>>>>>>>")
	fmt.Println(">>>>>>>>>>>>>>>> Listening to Node", listenTo)
	fmt.Println(">>>>>>>>>>>>>>>>")

	AddInterruptHandler(func() {
		fmt.Print("<Break>\n")
		fmt.Print("Gracefully shutting down the server...\n")
		for _, fnode := range fnodes {
			fmt.Print("Shutting Down: ", fnode.State.FactomNodeName, "\r\n")
			fnode.State.ShutdownChan <- 0
		}
		if enableNet {
			p2pNetwork.NetworkStop()
			// NODE_TALK_FIX
			p2pProxy.stopProxy()
		}
		fmt.Print("Waiting...\r\n")
		time.Sleep(3 * time.Second)
		os.Exit(0)
	})

	if journal != "" {
		if s.DBType != "Map" {
			fmt.Println("Journal is ALWAYS a Map database")
			s.DBType = "Map"
		}
	}
	if follower {
		s.NodeMode = "FULL"
		leadID := primitives.Sha([]byte(s.Prefix + "FNode0"))
		if s.IdentityChainID.IsSameAs(leadID) {
			s.SetIdentityChainID(primitives.Sha([]byte(time.Now().String()))) // Make sure this node is NOT a leader
		}
	}

	s.KeepMismatch = keepMismatch

	if len(db) > 0 {
		s.DBType = db
	} else {
		db = s.DBType
	}

	if len(cloneDB) > 0 {
		s.CloneDBType = cloneDB
	} else {
		s.CloneDBType = db
	}

	pnet := net
	if len(fnet) > 0 {
		pnet = fnet
		net = "file"
	}

	go StartProfiler()

	s.AddPrefix(prefix)
	s.SetOut(false)
	s.Init()
	s.SetDropRate(droprate)

	mLog.init(runtimeLog, cnt)

	setupFirstAuthority(s)

	os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "FNode 0 Salt", s.Salt.String()[:16]))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "enablenet", enableNet))
	os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "node", listenTo))
	os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "prefix", prefix))
	os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "node count", cnt))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "net spec", pnet))
	os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "Msgs droped", droprate))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "journal", journal))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "database", db))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "database for clones", cloneDB))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%d\"\n", "port", s.PortNumber))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "peers", peers))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%d\"\n", "netdebug", netdebug))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%t\"\n", "exclusive", exclusive))
	os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "block time", blkTime))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "runtimeLog", runtimeLog))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "rotate", rotate))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "timeOffset", timeOffset))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "keepMismatch", keepMismatch))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "startDelay", startDelay))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "Network", s.Network))
	os.Stderr.WriteString(fmt.Sprintf("%20s %x\n", "customnet", customNet))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "deadline (ms)", deadline))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "tls", s.FactomdTLSEnable))
	os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "selfaddr", s.FactomdLocations))
	os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "rpcuser", s.RpcUser))
	if "" == s.RpcPass {
		os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "rpcpass", "is blank"))
	} else {
		os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "rpcpass", "is set"))
	}

	//************************************************
	// Actually setup the Network
	//************************************************

	// Make cnt Factom nodes
	for i := 0; i < cnt; i++ {
		makeServer(s) // We clone s to make all of our servers
	}
	// Modify Identities of new nodes
	if len(fnodes) > 1 && len(s.Prefix) == 0 {
		modifyLoadIdentities() // We clone s to make all of our servers
	}

	for i := range fnodes {
		fnodes[i].State.CreateBlankFactomIdentity(fnodes[i].State.IdentityChainID)
	}

	// Start the P2P netowork
	var networkID p2p.NetworkID
	var seedURL, networkPort, specialPeers string
	switch s.Network {
	case "MAIN", "main":
		networkID = p2p.MainNet
		seedURL = s.MainSeedURL
		networkPort = s.MainNetworkPort
		specialPeers = s.MainSpecialPeers
	case "TEST", "test":
		networkID = p2p.TestNet
		seedURL = s.TestSeedURL
		networkPort = s.TestNetworkPort
		specialPeers = s.TestSpecialPeers
	case "LOCAL", "local":
		networkID = p2p.LocalNet
		seedURL = s.LocalSeedURL
		networkPort = s.LocalNetworkPort
		specialPeers = s.LocalSpecialPeers
	case "CUSTOM", "custom":
		if bytes.Compare(customNet, []byte("\xe3\xb0\xc4\x42")) == 0 {
			panic("Please specify a custom network with -customnet=<something unique here>")
		}
		s.CustomNetworkID = customNet
		networkID = p2p.NetworkID(binary.BigEndian.Uint32(customNet))
		for i := range fnodes {
			fnodes[i].State.CustomNetworkID = customNet
		}
		seedURL = s.LocalSeedURL
		networkPort = s.LocalNetworkPort
		specialPeers = s.LocalSpecialPeers
	default:
		panic("Invalid Network choice in Config File or command line. Choose MAIN, TEST, LOCAL, or CUSTOM")
	}

	connectionMetricsChannel := make(chan interface{}, p2p.StandardChannelSize)
	p2p.NetworkDeadline = time.Duration(deadline) * time.Millisecond

	if enableNet {

		if 0 < networkPortOverride {
			networkPort = fmt.Sprintf("%d", networkPortOverride)
		}
		ci := p2p.ControllerInit{
			Port:                     networkPort,
			PeersFile:                s.PeersFile,
			Network:                  networkID,
			Exclusive:                exclusive,
			SeedURL:                  seedURL,
			SpecialPeers:             specialPeers,
			ConnectionMetricsChannel: connectionMetricsChannel,
		}
		p2pNetwork = new(p2p.Controller).Init(ci)
		p2pNetwork.StartNetwork()
		// Setup the proxy (Which translates from network parcels to factom messages, handling addressing for directed messages)
		p2pProxy = new(P2PProxy).Init(fnodes[0].State.FactomNodeName, "P2P Network").(*P2PProxy)
		p2pProxy.FromNetwork = p2pNetwork.FromNetwork
		p2pProxy.ToNetwork = p2pNetwork.ToNetwork
		fnodes[0].Peers = append(fnodes[0].Peers, p2pProxy)
		p2pProxy.SetDebugMode(netdebug)
		if 0 < netdebug {
			go p2pProxy.PeriodicStatusReport(fnodes)
			p2pNetwork.StartLogging(uint8(netdebug))
		} else {
			p2pNetwork.StartLogging(uint8(0))
		}
		p2pProxy.StartProxy()
		// Command line peers lets us manually set special peers
		p2pNetwork.DialSpecialPeersString(peers)
	}

	switch net {
	case "file":
		file, err := os.Open(fnet)
		if err != nil {
			panic(fmt.Sprintf("File network.txt failed to open: %s", err.Error()))
		} else if file == nil {
			panic(fmt.Sprint("File network.txt failed to open, and we got a file of <nil>"))
		}
		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			var a, b int
			var s string
			fmt.Sscanf(scanner.Text(), "%d %s %d", &a, &s, &b)
			if s == "--" {
				AddSimPeer(fnodes, a, b)
			}
		}
	case "square":
		side := int(math.Sqrt(float64(cnt)))

		for i := 0; i < side; i++ {
			AddSimPeer(fnodes, i*side, (i+1)*side-1)
			AddSimPeer(fnodes, i, side*(side-1)+i)
			for j := 0; j < side; j++ {
				if j < side-1 {
					AddSimPeer(fnodes, i*side+j, i*side+j+1)
				}
				AddSimPeer(fnodes, i*side+j, ((i+1)*side)+j)
			}
		}
	case "long":
		fmt.Println("Using long Network")
		for i := 1; i < cnt; i++ {
			AddSimPeer(fnodes, i-1, i)
		}
		// Make long into a circle
	case "loops":
		fmt.Println("Using loops Network")
		for i := 1; i < cnt; i++ {
			AddSimPeer(fnodes, i-1, i)
		}
		for i := 0; (i+17)*2 < cnt; i += 17 {
			AddSimPeer(fnodes, i%cnt, (i+5)%cnt)
		}
		for i := 0; (i+13)*2 < cnt; i += 13 {
			AddSimPeer(fnodes, i%cnt, (i+7)%cnt)
		}
	case "alot":
		n := len(fnodes)
		for i := 0; i < n; i++ {
			AddSimPeer(fnodes, i, (i+1)%n)
			AddSimPeer(fnodes, i, (i+5)%n)
			AddSimPeer(fnodes, i, (i+7)%n)
		}

	case "alot+":
		n := len(fnodes)
		for i := 0; i < n; i++ {
			AddSimPeer(fnodes, i, (i+1)%n)
			AddSimPeer(fnodes, i, (i+5)%n)
			AddSimPeer(fnodes, i, (i+7)%n)
			AddSimPeer(fnodes, i, (i+13)%n)
		}

	case "tree":
		index := 0
		row := 1
	treeloop:
		for i := 0; true; i++ {
			for j := 0; j <= i; j++ {
				AddSimPeer(fnodes, index, row)
				AddSimPeer(fnodes, index, row+1)
				row++
				index++
				if index >= len(fnodes) {
					break treeloop
				}
			}
			row += 1
		}
	case "circles":
		circleSize := 7
		index := 0
		for {
			AddSimPeer(fnodes, index, index+circleSize-1)
			for i := index; i < index+circleSize-1; i++ {
				AddSimPeer(fnodes, i, i+1)
			}
			index += circleSize

			AddSimPeer(fnodes, index, index-circleSize/3)
			AddSimPeer(fnodes, index+2, index-circleSize-circleSize*2/3-1)
			AddSimPeer(fnodes, index+3, index-(2*circleSize)-circleSize*2/3)
			AddSimPeer(fnodes, index+5, index-(3*circleSize)-circleSize*2/3+1)

			if index >= len(fnodes) {
				break
			}
		}
	default:
		fmt.Println("Didn't understand network type. Known types: mesh, long, circles, tree, loops.  Using a Long Network")
		for i := 1; i < cnt; i++ {
			AddSimPeer(fnodes, i-1, i)
		}

	}
	if journal != "" {
		go LoadJournal(s, journal)
		startServers(false)
	} else {
		startServers(true)
	}

	// Start the webserver
	go wsapi.Start(fnodes[0].State)

	go controlPanel.ServeControlPanel(fnodes[0].State.ControlPanelChannel, fnodes[0].State, connectionMetricsChannel, p2pNetwork, Build)
	// Listen for commands:
	SimControl(listenTo)
}
示例#5
0
// MilliTimestamp is in milliseconds
func (t *Transaction) GetTimestamp() interfaces.Timestamp {
	return primitives.NewTimestampFromMilliseconds(t.MilliTimestamp)
}
示例#6
0
// Return the timestamp
func (c *CommitChain) GetTimestamp() interfaces.Timestamp {
	a := make([]byte, 2, 8)
	a = append(a, c.MilliTime[:]...)
	milli := uint64(binary.BigEndian.Uint64(a))
	return primitives.NewTimestampFromMilliseconds(milli)
}
示例#7
0
func (e *DirBlockInfo) GetTimestamp() interfaces.Timestamp {
	return primitives.NewTimestampFromMilliseconds(uint64(e.Timestamp))
}