コード例 #1
0
ファイル: consensusset.go プロジェクト: mantyr/Sia
// New returns a new ConsensusSet, containing at least the genesis block. If
// there is an existing block database present in the persist directory, it
// will be loaded.
func New(gateway modules.Gateway, persistDir string) (*ConsensusSet, error) {
	// Check for nil dependencies.
	if gateway == nil {
		return nil, errNilGateway
	}

	// Create the genesis block.
	genesisBlock := types.Block{
		Timestamp: types.GenesisTimestamp,
		Transactions: []types.Transaction{
			{SiafundOutputs: types.GenesisSiafundAllocation},
		},
	}

	// Create the ConsensusSet object.
	cs := &ConsensusSet{
		gateway: gateway,

		blockRoot: processedBlock{
			Block:       genesisBlock,
			ChildTarget: types.RootTarget,
			Depth:       types.RootDepth,

			DiffsGenerated: true,
		},

		dosBlocks: make(map[types.BlockID]struct{}),

		marshaler:       encoding.StdGenericMarshaler{},
		blockRuleHelper: stdBlockRuleHelper{},
		blockValidator:  NewBlockValidator(),

		persistDir: persistDir,
	}

	// Create the diffs for the genesis siafund outputs.
	for i, siafundOutput := range genesisBlock.Transactions[0].SiafundOutputs {
		sfid := genesisBlock.Transactions[0].SiafundOutputID(uint64(i))
		sfod := modules.SiafundOutputDiff{
			Direction:     modules.DiffApply,
			ID:            sfid,
			SiafundOutput: siafundOutput,
		}
		cs.blockRoot.SiafundOutputDiffs = append(cs.blockRoot.SiafundOutputDiffs, sfod)
	}

	// Initialize the consensus persistence structures.
	err := cs.initPersist()
	if err != nil {
		return nil, err
	}

	// Register RPCs
	gateway.RegisterRPC("SendBlocks", cs.sendBlocks)
	gateway.RegisterRPC("RelayBlock", cs.relayBlock)
	gateway.RegisterConnectCall("SendBlocks", cs.threadedReceiveBlocks)

	return cs, nil
}
コード例 #2
0
ファイル: consensusset.go プロジェクト: mm3/Sia
// New returns a new State, containing at least the genesis block. If there is
// an existing block database present in saveDir, it will be loaded. Otherwise,
// a new database will be created.
func New(gateway modules.Gateway, saveDir string) (*State, error) {
	if gateway == nil {
		return nil, ErrNilGateway
	}

	// Create the State object.
	cs := &State{
		blockMap:  make(map[types.BlockID]*blockNode),
		dosBlocks: make(map[types.BlockID]struct{}),

		currentPath: make([]types.BlockID, 1),

		siacoinOutputs:        make(map[types.SiacoinOutputID]types.SiacoinOutput),
		fileContracts:         make(map[types.FileContractID]types.FileContract),
		siafundOutputs:        make(map[types.SiafundOutputID]types.SiafundOutput),
		delayedSiacoinOutputs: make(map[types.BlockHeight]map[types.SiacoinOutputID]types.SiacoinOutput),

		gateway: gateway,

		mu: sync.New(modules.SafeMutexDelay, 1),
	}

	// Create the genesis block and add it as the BlockRoot.
	genesisBlock := types.Block{
		Timestamp: types.GenesisTimestamp,
		Transactions: []types.Transaction{
			{SiafundOutputs: types.GenesisSiafundAllocation},
		},
	}
	cs.blockRoot = &blockNode{
		block:       genesisBlock,
		childTarget: types.RootTarget,
		depth:       types.RootDepth,

		diffsGenerated: true,
	}
	cs.blockMap[genesisBlock.ID()] = cs.blockRoot

	// Fill out the consensus information for the genesis block.
	cs.currentPath[0] = genesisBlock.ID()
	cs.siacoinOutputs[genesisBlock.MinerPayoutID(0)] = types.SiacoinOutput{
		Value:      types.CalculateCoinbase(0),
		UnlockHash: types.ZeroUnlockHash,
	}

	// Allocate the Siafund addresses by putting them all in a big transaction
	// and applying the diffs.
	for i, siafundOutput := range genesisBlock.Transactions[0].SiafundOutputs {
		sfid := genesisBlock.Transactions[0].SiafundOutputID(i)
		sfod := modules.SiafundOutputDiff{
			Direction:     modules.DiffApply,
			ID:            sfid,
			SiafundOutput: siafundOutput,
		}
		cs.commitSiafundOutputDiff(sfod, modules.DiffApply)
		cs.blockRoot.siafundOutputDiffs = append(cs.blockRoot.siafundOutputDiffs, sfod)
	}

	// Send out genesis block update.
	cs.updateSubscribers(nil, []*blockNode{cs.blockRoot})

	// Create the consensus directory.
	err := os.MkdirAll(saveDir, 0700)
	if err != nil {
		return nil, err
	}

	// During short tests, use an in-memory database.
	if build.Release == "testing" && testing.Short() {
		cs.db = persist.NilDB
	} else {
		// Otherwise, try to load an existing database from disk.
		err = cs.load(saveDir)
		if err != nil {
			return nil, err
		}
	}

	// Register RPCs
	gateway.RegisterRPC("SendBlocks", cs.sendBlocks)
	gateway.RegisterRPC("RelayBlock", cs.RelayBlock)
	gateway.RegisterConnectCall("SendBlocks", cs.receiveBlocks)

	// Spawn resynchronize loop.
	go cs.threadedResynchronize()

	return cs, nil
}
コード例 #3
0
ファイル: consensusset.go プロジェクト: robvanmieghem/Sia
// New returns a new ConsensusSet, containing at least the genesis block. If
// there is an existing block database present in the persist directory, it
// will be loaded.
func New(gateway modules.Gateway, bootstrap bool, persistDir string) (*ConsensusSet, error) {
	// Check for nil dependencies.
	if gateway == nil {
		return nil, errNilGateway
	}

	// Create the ConsensusSet object.
	cs := &ConsensusSet{
		gateway: gateway,

		blockRoot: processedBlock{
			Block:       types.GenesisBlock,
			ChildTarget: types.RootTarget,
			Depth:       types.RootDepth,

			DiffsGenerated: true,
		},

		dosBlocks: make(map[types.BlockID]struct{}),

		marshaler:       encoding.StdGenericMarshaler{},
		blockRuleHelper: stdBlockRuleHelper{},
		blockValidator:  NewBlockValidator(),

		persistDir: persistDir,
	}

	// Create the diffs for the genesis siafund outputs.
	for i, siafundOutput := range types.GenesisBlock.Transactions[0].SiafundOutputs {
		sfid := types.GenesisBlock.Transactions[0].SiafundOutputID(uint64(i))
		sfod := modules.SiafundOutputDiff{
			Direction:     modules.DiffApply,
			ID:            sfid,
			SiafundOutput: siafundOutput,
		}
		cs.blockRoot.SiafundOutputDiffs = append(cs.blockRoot.SiafundOutputDiffs, sfod)
	}

	// Initialize the consensus persistence structures.
	err := cs.initPersist()
	if err != nil {
		return nil, err
	}

	go func() {
		// Sync with the network. Don't sync if we are testing because
		// typically we don't have any mock peers to synchronize with in
		// testing.
		if bootstrap {
			// We are in a virgin goroutine right now, so calling the threaded
			// function without a goroutine is okay.
			err = cs.threadedInitialBlockchainDownload()
			if err != nil {
				return
			}
		}

		// threadedInitialBlockchainDownload will release the threadgroup 'Add'
		// it was holding, so another needs to be grabbed to finish off this
		// goroutine.
		err = cs.tg.Add()
		if err != nil {
			return
		}
		defer cs.tg.Done()

		// Register RPCs
		gateway.RegisterRPC("SendBlocks", cs.rpcSendBlocks)
		gateway.RegisterRPC("RelayBlock", cs.rpcRelayBlock) // COMPATv0.5.1
		gateway.RegisterRPC("RelayHeader", cs.threadedRPCRelayHeader)
		gateway.RegisterRPC("SendBlk", cs.rpcSendBlk)
		gateway.RegisterConnectCall("SendBlocks", cs.threadedReceiveBlocks)
		cs.tg.OnStop(func() {
			cs.gateway.UnregisterRPC("SendBlocks")
			cs.gateway.UnregisterRPC("RelayBlock")
			cs.gateway.UnregisterRPC("RelayHeader")
			cs.gateway.UnregisterRPC("SendBlk")
			cs.gateway.UnregisterConnectCall("SendBlocks")
		})

		// Mark that we are synced with the network.
		cs.mu.Lock()
		cs.synced = true
		cs.mu.Unlock()
	}()

	return cs, nil
}
コード例 #4
0
ファイル: consensusset.go プロジェクト: kustomzone/Sia
// New returns a new ConsensusSet, containing at least the genesis block. If
// there is an existing block database present in saveDir, it will be loaded.
// Otherwise, a new database will be created.
func New(gateway modules.Gateway, saveDir string) (*ConsensusSet, error) {
	if gateway == nil {
		return nil, ErrNilGateway
	}

	// Create the genesis block.
	genesisBlock := types.Block{
		Timestamp: types.GenesisTimestamp,
		Transactions: []types.Transaction{
			{SiafundOutputs: types.GenesisSiafundAllocation},
		},
	}

	// Create the ConsensusSet object.
	cs := &ConsensusSet{
		gateway: gateway,

		blockRoot: processedBlock{
			Block:       genesisBlock,
			ChildTarget: types.RootTarget,
			Depth:       types.RootDepth,

			DiffsGenerated: true,
		},

		dosBlocks: make(map[types.BlockID]struct{}),

		mu: sync.New(modules.SafeMutexDelay, 1),
	}

	// Allocate the Siafund addresses by putting them all in a big transaction inside the genesis block
	for i, siafundOutput := range genesisBlock.Transactions[0].SiafundOutputs {
		sfid := genesisBlock.Transactions[0].SiafundOutputID(i)
		sfod := modules.SiafundOutputDiff{
			Direction:     modules.DiffApply,
			ID:            sfid,
			SiafundOutput: siafundOutput,
		}
		cs.blockRoot.SiafundOutputDiffs = append(cs.blockRoot.SiafundOutputDiffs, sfod)
	}

	// Create the consensus directory.
	err := os.MkdirAll(saveDir, 0700)
	if err != nil {
		return nil, err
	}

	// Try to load an existing database from disk.
	err = cs.load(saveDir)
	if err != nil {
		return nil, err
	}

	// Send the genesis block to subscribers.
	cs.updateSubscribers(nil, []*processedBlock{&cs.blockRoot})

	// Send any blocks that were loaded from disk to subscribers.
	cs.loadDiffs()

	// Register RPCs
	gateway.RegisterRPC("SendBlocks", cs.sendBlocks)
	gateway.RegisterRPC("RelayBlock", cs.RelayBlock)
	gateway.RegisterConnectCall("SendBlocks", cs.receiveBlocks)

	return cs, nil
}
コード例 #5
0
ファイル: consensusset.go プロジェクト: CSSZiegler/Sia
// New returns a new ConsensusSet, containing at least the genesis block. If
// there is an existing block database present in the persist directory, it
// will be loaded.
func New(gateway modules.Gateway, persistDir string) (*ConsensusSet, error) {
	// Check for nil dependencies.
	if gateway == nil {
		return nil, errNilGateway
	}

	// Create the ConsensusSet object.
	cs := &ConsensusSet{
		gateway: gateway,

		blockRoot: processedBlock{
			Block:       types.GenesisBlock,
			ChildTarget: types.RootTarget,
			Depth:       types.RootDepth,

			DiffsGenerated: true,
		},

		dosBlocks: make(map[types.BlockID]struct{}),

		marshaler:       encoding.StdGenericMarshaler{},
		blockRuleHelper: stdBlockRuleHelper{},
		blockValidator:  NewBlockValidator(),

		persistDir: persistDir,
	}

	// Create the diffs for the genesis siafund outputs.
	for i, siafundOutput := range types.GenesisBlock.Transactions[0].SiafundOutputs {
		sfid := types.GenesisBlock.Transactions[0].SiafundOutputID(uint64(i))
		sfod := modules.SiafundOutputDiff{
			Direction:     modules.DiffApply,
			ID:            sfid,
			SiafundOutput: siafundOutput,
		}
		cs.blockRoot.SiafundOutputDiffs = append(cs.blockRoot.SiafundOutputDiffs, sfod)
	}

	// Initialize the consensus persistence structures.
	err := cs.initPersist()
	if err != nil {
		return nil, err
	}

	go func() {
		// Sync with the network. Don't sync if we are testing because typically we
		// don't have any mock peers to synchronize with in testing.
		// TODO: figure out a better way to conditionally do IBD. Otherwise this block will never be tested.
		if build.Release != "testing" {
			cs.threadedInitialBlockchainDownload()
		}

		// Register RPCs
		gateway.RegisterRPC("SendBlocks", cs.rpcSendBlocks)
		gateway.RegisterRPC("RelayBlock", cs.rpcRelayBlock) // COMPATv0.5.1
		gateway.RegisterRPC("RelayHeader", cs.rpcRelayHeader)
		gateway.RegisterRPC("SendBlk", cs.rpcSendBlk)
		gateway.RegisterConnectCall("SendBlocks", cs.threadedReceiveBlocks)

		// Mark that we are synced with the network.
		cs.mu.Lock()
		cs.synced = true
		cs.mu.Unlock()
	}()

	return cs, nil
}