c语言sscanf函数的用法是什么
257
2022-11-29
100行代码实现一个区块链!
废话不多说,开始跟我用golang搭建个迷你区块链:
首先,引入包:
package mainimport ( "bytes" "crypto/sha256" "encoding/binary" "fmt" "math" "math/big" "time")
设置一些常量,工作量证明难度系数dif,搜索上界INT64_MAX:
const ( dif = 20 INT64_MAX = math.MaxInt64)
然后我们设计一个简单的区块体和区块链体,每个区块呢有前个区块哈希,本区块哈希,数据,链长,时间戳和随机数:
type Block struct { PrevHash []byte Hash []byte Data string Height int64 Timestamp int64 Nonce int}type BlockChain struct { Blocks []Block}
实现一段工作量证明函数,这个工作量证明呢以后聊共识算法会细讲的,也就是这里实现了不可篡改(reigns最近被raft血虐的,TAT):
func IntToHex(num int64) []byte { buff := new(bytes.Buffer) err := binary.Write(buff, binary.BigEndian, num) if err != nil { panic(err) } return buff.Bytes()}func ProofOfWork(b Block, dif int) ([]byte, int) { target := big.NewInt(1) target.Lsh(target, uint(256-dif)) nonce := 0 for ; nonce < INT64_MAX; nonce++ { check := bytes.Join( [][]byte{b.PrevHash, []byte(b.Data), IntToHex(b.Height), IntToHex(b.Timestamp), IntToHex(int64(nonce))}, []byte{}) hash := sha256.Sum256(check) var hashInt big.Int hashInt.SetBytes(hash[:]) if hashInt.Cmp(target) == -1 { return hash[:], nonce } } return []byte(""), nonce}
然后呢这段函数实现生成创世块,也就是链头啦:
func GenesisBlock(data string) BlockChain { var bc BlockChain bc.Blocks = make([]Block, 1) bc.Blocks[0] = Block{ PrevHash: []byte(""), Data: data, Height: 1, Timestamp: time.Now().Unix(), } bc.Blocks[0].Hash, bc.Blocks[0].Nonce = ProofOfWork(bc.Blocks[0], dif) return bc}
这段呢是生成新的区块,也就是俗称的挖矿,当然了真实的挖矿可比这个复杂多了:
func GenerateBlock(bc *BlockChain, data string) { prevBlock := bc.Blocks[len(bc.Blocks)-1] block := Block{ PrevHash: prevBlock.Hash, Data: data, Height: prevBlock.Height + 1, Timestamp: time.Now().Unix(), } block.Hash, block.Nonce = ProofOfWork(block, dif) bc.Blocks = append(bc.Blocks, block)}
再写个打印区块函数:
func Print(bc BlockChain) { for _, i := range bc.Blocks { fmt.Printf("PrevHash: %x\n", i.PrevHash) fmt.Printf("Hash: %x\n", i.Hash) fmt.Println("Block's Data: ", i.Data) fmt.Println("Current Height: ", i.Height) fmt.Println("Timestamp: ", i.Timestamp) fmt.Println("Nonce: ", i.Nonce) }}
好啦,各个函数都写完了,不多不少99行
。
写个main函数看看吧~
来,reigns开始挖矿,先挖个创世块,给alice转账2刀,然后再给alice转3刀,看看这几次次操作怎么记录在区块链中吧:
func main() { blockchain := GenesisBlock("i am reigns") GenerateBlock(&blockchain, "send 2$ to alice") GenerateBlock(&blockchain, "send 3$ to alice") Print(blockchain)}
输出结果:
由于创世块没有前面的区块,所以他的PrevHash就是空,记录给alice转账2刀的这个区块,它的PrevHash就是创世块了,后面的以此类推,得到一个不可篡改链。
也可以发现啊,区块生成并不是一下子执行完成的,三个区块用了接近7秒钟,这就是工作量证明算法起的作用了,防止恶意节点不劳而获,每个新的区块都需要付出一定计算力才能得到,当然这里没有设置很高的困难度(dif = 20),也没有根据时间动态增加难度,比特币网络中一般设置的挖矿难度都需要10分钟左右的,想想2009年的10分钟和2019的10分钟,难度提了多少~
怎么样,是不是了解了区块链的基本结构呢,当然了成熟的链使用的数据存储结构肯定不会是一个字符串,比如比特币用的是默克尔树,交易也不会这么随便就成功,都需要依靠一个叫做智能合约的东东进行约束的。
好啦,今天就讲这么多。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~