初链主网Beta版上线的技术解读----部分代码解读

从2017年11月启动至今,经过历时近一年的研究、开发与测试,初链主网Beta版于新加坡时间2018年09月28日08:00正式上线。从2018年的4月份左右的时间加入初链技术社区到Beta版上线,亲眼看到,初链的一步一步的发展,经历着接近于从无到有的过程,心里说不出的愉悦感。所以在参与翻译并解读黄皮书任务之后,接下了Beta版的技术解读。初链对于我而言,感觉像是亲人,看着初链一步一步的发展壮大,到现在这么庞大的技术社区的运营,真的很快,也很迅速,希望以后会越来越好。

下面进入正题。总所周知,初链主网Beta版在新加坡已经正式上线。Beta版的亮点主要有以下几点,且听我慢慢道来:

1、全球首家实现无许可(Permissionless)环境下的混合共识公链,科学采用双链结构,并已在美国获得先行专利

2、全球首家在工程上实现将水果链整合到PoW,发布自己的FPOW机制的公链

3、原创性的推出TrueHash,实现不依赖手动调整,从而根本上抗ASIC的挖矿算法

4、原创性实现安全的混合共识PBFT委员会的随机选举机制

5、在尚未实现Sharding技术情况下,在内测阶段的每秒钟交易速度TPS均值达到1200左右,峰值达到1900左右

TrueScan浏览器的URL地址是: www.truescan.net 。

truechain源码GitHub地址:https://github.com/truechain/truechain-engineering-code

下面的图是初链一句源码生成的的UML类图,可以大致的了解一下:

下面,我只针对一个部分,进行部分源码的分析 -- 。

BlockChain表示给定具有起源的数据库的规范链。BlockChain 的结构如下:

type BlockChain struct {
	chainConfig *params.ChainConfig // Chain & network configuration
	cacheConfig *CacheConfig        // Cache configuration for pruning

	db     ethdb.Database // Low level persistent database to store final content in
	triegc *prque.Prque   // Priority queue mapping block numbers to tries to gc
	gcproc time.Duration  // Accumulates canonical block processing for trie dumping

	hc               *HeaderChain
	sc               *snailchain.SnailBlockChain
	rmLogsFeed       event.Feed
	chainFeed        event.Feed
	chainSideFeed    event.Feed
	chainHeadFeed    event.Feed
	logsFeed         event.Feed
	RewardNumberFeed event.Feed
	scope            event.SubscriptionScope
	genesisBlock     *types.Block

	mu      sync.RWMutex // global mutex for locking chain operations
	chainmu sync.RWMutex // blockchain insertion lock
	procmu  sync.RWMutex // block processor lock

	checkpoint       int          // checkpoint counts towards the new checkpoint
	currentBlock     atomic.Value // Current head of the block chain
	currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!)
	currentReward    atomic.Value // Current head of the currentReward

	stateCache   state.Database // State database to reuse between imports (contains state cache)
	bodyCache    *lru.Cache     // Cache for the most recent block bodies
	signCache    *lru.Cache     // Cache for the most recent block bodies
	bodyRLPCache *lru.Cache     // Cache for the most recent block bodies in RLP encoded format
	blockCache   *lru.Cache     // Cache for the most recent entire blocks
	futureBlocks *lru.Cache     // future blocks are blocks added for later processing
	rewardCache  *lru.Cache

	quit    chan struct{} // blockchain quit channel
	running int32         // running must be called atomically
	// procInterrupt must be atomically called
	procInterrupt int32          // interrupt signaler for block processing
	wg            sync.WaitGroup // chain processing wait group for shutting down

	engine    consensus.Engine
	processor Processor // block processor interface
	validator Validator // block and state validator interface
	vmConfig  vm.Config

	badBlocks *lru.Cache // Bad block cache
}

NewBlockChain使用信息返回完全初始化的块链在数据库中可用。 它初始化默认的以太坊验证器和处理器。

func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig,
	chainConfig *params.ChainConfig, engine consensus.Engine,
	vmConfig vm.Config) (*BlockChain, error) {

	if cacheConfig == nil {
		cacheConfig = &CacheConfig{
			TrieNodeLimit: 256 * 1024 * 1024,
			TrieTimeLimit: 5 * time.Minute,
		}
	}
	bodyCache, _ := lru.New(bodyCacheLimit)
	bodyRLPCache, _ := lru.New(bodyCacheLimit)
	blockCache, _ := lru.New(blockCacheLimit)
	futureBlocks, _ := lru.New(maxFutureBlocks)
	badBlocks, _ := lru.New(badBlockLimit)
	signCache, _ := lru.New(bodyCacheLimit)
	rewardCache, _ := lru.New(bodyCacheLimit)

	bc := &BlockChain{
		chainConfig:  chainConfig,
		cacheConfig:  cacheConfig,
		db:           db,
		triegc:       prque.New(),
		stateCache:   state.NewDatabase(db),
		quit:         make(chan struct{}),
		bodyCache:    bodyCache,
		signCache:    signCache,
		bodyRLPCache: bodyRLPCache,
		blockCache:   blockCache,
		futureBlocks: futureBlocks,
		rewardCache:  rewardCache,
		engine:       engine,
		vmConfig:     vmConfig,
		badBlocks:    badBlocks,
	}
	bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
	bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))

	var err error
	bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.getProcInterrupt)
	if err != nil {
		return nil, err
	}
	bc.genesisBlock = bc.GetBlockByNumber(0)
	if bc.genesisBlock == nil {
		return nil, ErrNoGenesis
	}
	if err := bc.loadLastState(); err != nil {
		return nil, err
	}
	// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
	//for hash := range BadHashes {
	//	if header := bc.GetHeaderByHash(hash); header != nil {
	//
	//		// get the canonical block corresponding to the offending header's number
	//		headerByNumber := bc.GetHeaderByNumber(header.Number.Uint64())
	//
	//		// make sure the headerByNumber (if present) is in our current canonical chain
	//		if headerByNumber != nil && headerByNumber.Hash() == header.Hash() {
	//			log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash)
	//			bc.SetHead(header.Number.Uint64() - 1)
	//			log.Error("Chain rewind was successful, resuming normal operation")
	//		}
	//	}
	//}

	// Take ownership of this particular state
	go bc.update()
	return bc, nil
}

loadLastState从数据库加载最后一个已知的链状态。 这种方法假设链管理器互斥锁被保留。

func (bc *BlockChain) loadLastState() error {
	// Restore the last known head block
	head := rawdb.ReadHeadBlockHash(bc.db)
	if head == (common.Hash{}) {
		// Corrupt or empty database, init from scratch
		log.Warn("Empty database, resetting chain")
		return bc.Reset()
	}

	// Make sure the entire head block is available
	currentBlock := bc.GetBlockByHash(head)
	if currentBlock == nil {
		// Corrupt or empty database, init from scratch
		log.Warn("Head block missing, resetting chain", "hash", head)
		return bc.Reset()
	}
	// Make sure the state associated with the block is available
	if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil {
		// Dangling block without a state associated, init from scratch
		log.Warn("Head state missing, repairing chain", "number", currentBlock.Number(), "hash", currentBlock.Hash())
		if err := bc.repair(&currentBlock); err != nil {
			return err
		}
	}
	// Everything seems to be fine, set as the head block
	bc.currentBlock.Store(currentBlock)

	// Restore the last known head header
	currentHeader := currentBlock.Header()
	if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) {
		if header := bc.GetHeaderByHash(head); header != nil {
			currentHeader = header
		}
	}
	bc.hc.SetCurrentHeader(currentHeader)

	// Restore the last known head fast block
	bc.currentFastBlock.Store(currentBlock)
	if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) {
		if block := bc.GetBlockByHash(head); block != nil {
			bc.currentFastBlock.Store(block)
		}
	}
	// Restore the last known currentReward

	rewardHead := rawdb.ReadHeadRewardNumber(bc.db)
	if rewardHead != 0 {
		reward := rawdb.ReadBlockReward(bc.db, rewardHead)
		//reward := bc.GetFastHeightBySnailHeight(rewardHead)
		bc.currentReward.Store(reward)
	}

	// Issue a status log for the user
	currentFastBlock := bc.CurrentFastBlock()

	//headerTd := bc.GetTd(currentHeader.Hash(), currentHeader..UintNumber64())
	//blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
	//fastTd := bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64())

	//log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd)
	//log.Info("Loaded most recent local full block", "number", currentBlock.Number(), "hash", currentBlock.Hash(), "td", blockTd)
	//log.Info("Loaded most recent local fast block", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash(), "td", fastTd)

	log.Info("Loaded most recent local Fastheader", "number", currentHeader.Number, "hash", currentHeader.Hash())
	log.Info("Loaded most recent local full Fastblock", "number", currentBlock.Number(), "hash", currentBlock.Hash())
	log.Info("Loaded most recent local fast Fastblock", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash())
	return nil
}

SetHead将本地链回卷到新的头部。 在标题的情况下,一切将删除新头部以上的新头部。 在块的情况下但是,如果缺少块体,则可以进一步重绕头部(非存档快速同步后的节点)。

func (bc *BlockChain) SetHead(head uint64) error {
	log.Warn("Rewinding blockchain", "target", head)

	bc.mu.Lock()
	defer bc.mu.Unlock()

	// Rewind the header chain, deleting all block bodies until then
	delFn := func(db rawdb.DatabaseDeleter, hash common.Hash, num uint64) {
		rawdb.DeleteBody(db, hash, num)
	}
	bc.hc.SetHead(head, delFn)
	currentHeader := bc.hc.CurrentHeader()

	// Clear out any stale content from the caches
	bc.bodyCache.Purge()
	bc.bodyRLPCache.Purge()
	bc.blockCache.Purge()
	bc.futureBlocks.Purge()

	// Rewind the block chain, ensuring we don't end up with a stateless head block
	if currentBlock := bc.CurrentBlock(); currentBlock != nil && currentHeader.Number.Uint64() < currentBlock.NumberU64() {
		bc.currentBlock.Store(bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64()))
	}
	if currentBlock := bc.CurrentBlock(); currentBlock != nil {
		if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil {
			// Rewound state missing, rolled back to before pivot, reset to genesis
			bc.currentBlock.Store(bc.genesisBlock)
		}
	}

	// If either blocks reached nil, reset to the genesis state
	if currentBlock := bc.CurrentBlock(); currentBlock == nil {
		bc.currentBlock.Store(bc.genesisBlock)
	}

	// Restore the last known currentReward
	currentReward := bc.GetLastRow()
	if currentReward != nil {
		bc.currentReward.Store(currentReward)
	}

	currentBlock := bc.CurrentBlock()
	rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash())

	return bc.loadLastState()
}

FastSyncCommitHead将当前头块设置为哈希定义的头块:

func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
	// Make sure that both the block as well at its state trie exists
	block := bc.GetBlockByHash(hash)
	if block == nil {
		return fmt.Errorf("non existent block [%x…]", hash[:4])
	}
	if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB(), 0); err != nil {
		return err
	}
	// If all checks out, manually set the head block
	bc.mu.Lock()
	bc.currentBlock.Store(block)
	bc.mu.Unlock()

	log.Info("Committed new head block", "number", block.Number(), "hash", hash)
	return nil
}

GasLimit返回当前HEAD块的gas极限:

func (bc *BlockChain) GasLimit() uint64 {
	return bc.CurrentBlock().GasLimit()
}

CurrentBlock检索规范链的当前头块。从区块链的内部缓存中检索块。

func (bc *BlockChain) CurrentBlock() *types.Block {
	return bc.currentBlock.Load().(*types.Block)
}

InsertHeaderChain尝试将给定的标题链插入到本地链,可能创建一个reorg。 如果返回错误,它将返回错误失败标头的索引号以及描述错误的错误。验证参数可用于微调nonce验证应该做或不做。 可选检查背后的原因是因为一些标头检索机制已经需要验证nonce,以及因为可以稀疏地验证nonce,而不需要检查每个。

func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
	start := time.Now()
	if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
		return i, err
	}

	// Make sure only one thread manipulates the chain at once
	bc.chainmu.Lock()
	defer bc.chainmu.Unlock()

	bc.wg.Add(1)
	defer bc.wg.Done()

	whFunc := func(header *types.Header) error {
		bc.mu.Lock()
		defer bc.mu.Unlock()

		_, err := bc.hc.WriteHeader(header)
		return err
	}

	return bc.hc.InsertHeaderChain(chain, whFunc, start)
}

writeHeader将标头写入本地链,因为它的父节点是已经知道 如果新插入的标题的总难度变为大于当前已知的TD,规范链被重新路由。两种情况:纯标题操作模式(轻客户端)或正确分隔的头/块阶段(非归档客户端)。

func (bc *BlockChain) writeHeader(header *types.Header) error {
	bc.wg.Add(1)
	defer bc.wg.Done()

	bc.mu.Lock()
	defer bc.mu.Unlock()

	_, err := bc.hc.WriteHeader(header)
	return err
}

 

《宾馆客房管理系统》是一个基于C#与MySQL的项目,旨在帮助学习者掌握数据库管理和系统开发知识。该项目通过完整代码实现,将编程技术应用于宾馆客房管理的实际业务场景。 C#是微软开发的面向对象编程语言,广泛用于Windows应用程序开发。在本项目中,C#用于构建用户界面、处理业务逻辑以及与数据库交互。它拥有丰富的类库,便于开发复杂图形用户界面(GUI),并通过ADO.NET组件实现与MySQL数据库的连接。MySQL是一种流行的开源关系型数据库管理系统(RDBMS),常用于Web应用程序,用于存储客房、预订、客户等核心数据。通过SQL语句,开发者可对数据进行增、删、改、查操作。系统中可能涉及“客房表”“预订表”“客户表”等,包含客房编号、类型、价格、预订日期等字段。 数据库连接是系统的关键部分。C#通过ADO.NET的SqlConnection类连接MySQL数据库,连接字符串包含服务器地址、数据库名称、用户名和密码。用户下载项目后,需根据本地环境修改连接字符串中的用户名和密码。系统要功能模块包括:客房管理,可展示、添加、修改、删除客房信息;预订管理,处理预订的查看、新增、修改和取消;客户管理,存储和管理客户个人信息;查询功能,支持按客房类型、价格范围、预订日期等条件查询;报表和统计功能,生成入住率、收入统计等报表辅助决策。开发者需编写C#方法对应数据库操作,同时设计直观易用的界面,方便用户完成预订流程。项目中的MySQL文件可能是数据库脚本或配置文件,包含建表、数据填充及权限设置等内容,用户需在本地测试前运行脚本设置数据库环境。 总之,该系统结合C#和MySQL,为学习者提供了一个涵盖数据库设计、业务逻辑处理和界面开发的综合实践案例,有助于提升开发者在数据库应用和系统集成方面的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值