前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >区块链数据结构

区块链数据结构

作者头像
Al1ex
发布于 2023-08-10 01:07:58
发布于 2023-08-10 01:07:58
72900
代码可运行
举报
文章被收录于专栏:网络安全攻防网络安全攻防
运行总次数:0
代码可运行
文章前言

区块链是近年来备受关注的技术,它的出现为数字货币、智能合约等领域带来了革命性的变革,然而区块链的实现并不简单,其中的数据结构是至关重要的一部分。本文将介绍区块链的数据结构,帮助读者更好地理解区块链的运作原理,通过本文的学习,读者将能够更好地理解区块链的本质并为后续的区块链开发及应用打下坚实的基础

区块结构

区块是一种记录交易的数据结构,每个区块由区块头和区块主体组成,区块主体负责记录前一段时间内的所有交易信息,区块链的大部分功能都由区块头实现,区块头数据结构包含以下几个部分:

  • 版本号(Version):表示当前区块的版本号,用于标识当前区块所使用的协议和规范
  • 父区块哈希值(Previous Block Hash):表示当前区块之前一个区块的哈希值,这样就形成了区块链的不可篡改性
  • Merkle根(Merkle Root):表示当前区块中所有交易信息的Merkle树根哈希值,用于保证区块中交易信息的完整性
  • 时间戳(Timestamp):表示当前区块的时间戳,用于记录区块的产生时间
  • 难度目标(Difficulty Target):表示当前区块的哈希值必须满足的难度目标,这个值是根据当前网络计算出来的,用于保证区块链的安全性和可靠性
  • 随机数(Nonce):用于计算区块哈希值的随机数,通过不断尝试不同的随机数以满足难度目标为目的,从而保证区块的唯一性和完整性

下面是一个区块链头部的示意图,需要注意的是区块头中的前一区块哈希值、Merkle根和难度目标等元数据信息都是通过哈希计算得到的并以此来保证区块的完整性和安全性,如果有人试图篡改某个区块的交易信息或者区块头,必须要重新计算该区块后面所有区块的哈希值,这是非常困难和耗费大量计算资源的,因此区块头是保证区块链安全性和可靠性的重要组成部分

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-------------------------------------------------------+
|                                                       |
|           +----------------------+                    |
|           | Version              |                    |
|           | Previous Block Hash  |                    |
|           | Merkle Root          |                    |
|           | Timestamp            |                    |
|           | Difficulty Target    |                    |
|           | Nonce                |                    |
|           +----------------------+                    |
|                                                       |
+-------------------------------------------------------+

区块链中的区块体(Block Body)是区块数据结构中的另一个重要组成部分,它包含了一定数量的交易信息,记录了所有的交易信息并保证了区块链的去中心化和可靠性,区块体的数据结构通常包含以下几个部分:

  • 交易记录(Transactions):表示当前区块中包含的交易信息,每个交易都包含了交易双方的地址、交易金额、交易时间等信息
  • 交易计数器(Transaction Counter):表示当前区块中包含的交易数量,用于区分不同的区块

区块链中的区块体示意图如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-------------------------------------------------------+
|                                                       |
|           +----------------------+                    |
|           | Transactions         |                    |
|           +----------------------+                    |
|           | Transaction 1        |                    |
|           | Transaction 2        |                    |
|           | Transaction 3        |                    |
|           | ...                  |                    |
|           +----------------------+                    |
|           | Transaction Counter  |                    |
|           +----------------------+                    |
|                                                       |
+-------------------------------------------------------+

区块体中的交易记录是区块链的核心内容之一,它记录了所有的交易信息并保证了区块链的去中心化和可靠性,交易记录中包含了交易双方的地址、交易金额、交易时间等信息,同时也包含了数字签名等信息,用于验证交易的合法性和完整性,交易计数器则用于记录当前区块中包含的交易数量,用于区分不同的区块,避免区块重复或丢失的情况

综上所述,我们可以得到一个完整的区块链中区块的示意图:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-------------------------------------------------------+
|                                                       |
|           +----------------------+                    |
|           | Block Header         |                    |
|           +----------------------+                    |
|           | Version              |                    |
|           | Previous Block Hash  |                    |
|           | Merkle Root          |                    |
|           | Timestamp            |                    |
|           | Difficulty Target    |                    |
|           | Nonce                |                    |
|           +----------------------+                    |
|                                                       |
|           +----------------------+                    |
|           | Transactions         |                    |
|           +----------------------+                    |
|           | Transaction 1        |                    |
|           | Transaction 2        |                    |
|           | Transaction 3        |                    |
|           | ...                  |                    |
|           +----------------------+                    |
|                                                       |
|                                                       |
|           +----------------------+                    |
|           | Block Hash           |                    |
|           +----------------------+                    |
|                                                       |
+-------------------------------------------------------+

以下是使用Go语言声明一个简单的区块链区块数据结构的测试代码,其中声明了一个区块结构体Block和一个交易结构体Transaction并实现了计算区块哈希值的方法calculateHash和创建新区块的方法newBlock,在测试代码中创建了一个创世区块和一个新区块并输出了新区块的各项信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
  "crypto/sha256"
  "encoding/hex"
  "time"
)

// 区块结构体
type Block struct {
  // 区块头
  Version       int64  // 版本号
  PreviousHash  string // 前一区块哈希值
  MerkleRoot    string // Merkle 根哈希值
  Timestamp     int64  // 时间戳
  Difficulty    int64  // 难度目标
  Nonce         int64  // 随机数
  // 区块体
  Transactions  []*Transaction // 交易信息
  TransactionNum int64          // 交易数量
}

// 交易结构体
type Transaction struct {
  From   string // 发送方地址
  To     string // 接收方地址
  Amount int64  // 交易金额
  Time   int64  // 交易时间
}

// 计算区块哈希值
func (b *Block) calculateHash() string {
  blockData := string(b.Version) + b.PreviousHash + b.MerkleRoot + string(b.Timestamp) + string(b.Difficulty) + string(b.Nonce)
  hash := sha256.Sum256([]byte(blockData))
  return hex.EncodeToString(hash[:])
}

// 创建新区块
func newBlock(previousBlock *Block, transactions []*Transaction) *Block {
  block := &Block{
    Version:        1,
    PreviousHash:   previousBlock.calculateHash(),
    MerkleRoot:     "merkle_root",
    Timestamp:      time.Now().UnixNano(),
    Difficulty:     1,
    Nonce:          0,
    Transactions:   transactions,
    TransactionNum: int64(len(transactions)),
  }
  return block
}

// 测试代码
func main() {
  // 创建创世区块
  genesisBlock := &Block{
    Version:        1,
    PreviousHash:   "",
    MerkleRoot:     "merkle_root",
    Timestamp:      time.Now().UnixNano(),
    Difficulty:     1,
    Nonce:          0,
    Transactions:   []*Transaction{},
    TransactionNum: 0,
  }
  // 创建新区块
  transactions := []*Transaction{
    {From: "alice", To: "bob", Amount: 10, Time: time.Now().UnixNano()},
    {From: "bob", To: "charlie", Amount: 5, Time: time.Now().UnixNano()},
  }
  newBlock := newBlock(genesisBlock, transactions)
  // 输出新区块信息
  println("Block Version:", newBlock.Version)
  println("Previous Block Hash:", newBlock.PreviousHash)
  println("Merkle Root Hash:", newBlock.MerkleRoot)
  println("Timestamp:", newBlock.Timestamp)
  println("Difficulty Target:", newBlock.Difficulty)
  println("Nonce:", newBlock.Nonce)
  println("Transactions:", newBlock.Transactions)
  println("Transaction Number:", newBlock.TransactionNum)
  println("Block Hash:", newBlock.calculateHash())
}
哈希算法

Hash算法又称散列算法,它是一种将任意长度的消息转换为固定长度输出的算法,Hash算法的主要应用场景包括数据完整性校验、数据加密、数字签名等。

Hash算法可以分为以下几类:

  • 消息摘要算法:将任意长度的消息转换为固定长度的哈希值,常用的算法包括MD5、SHA-1、SHA-2、SHA-3等
  • 消息认证码算法:在消息摘要算法的基础上增加了密钥,用于验证消息的完整性和真实性,常用的算法包括HMAC、CMAC等
  • 公钥密码学算法:包括数字签名、密钥交换、加密等功能,常用的算法包括RSA、DSA、ECDSA、Diffie-Hellman、ElGamal等

以下是一个使用Go语言实现SHA-256消息摘要算法的示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
  "crypto/sha256"
  "encoding/hex"
  "fmt"
)

func main() {
  // 定义消息
  message := "Hello, world!"
  // 计算SHA-256哈希值
  hash := sha256.Sum256([]byte(message))
  // 输出哈希值
  fmt.Println("Message:", message)
  fmt.Println("Hash:", hex.EncodeToString(hash[:]))
}

以上示例代码中通过调用Go语言标准库中的crypto/sha256包实现了SHA-256哈希算法,首先定义了一个消息字符串message,然后调用sha256.Sum256方法计算哈希值并使用hex.EncodeToString方法将哈希值转换为十六进制字符串进行输出,由于Hash算法是不可逆的,即无法从哈希值反推出原始消息,因此在实际应用中需要对原始消息进行哈希计算并将哈希值与消息一起进行存储和传输以保证数据的完整性和真实性

椭圆曲线
基本介绍

椭圆曲线加密算法(Elliptic Curve Cryptography,ECC)是基于椭圆曲线数学理论实现的一种非对称加密算法,相比RSA,ECC优势是可以使用更短的密钥来实现与RSA相当或更高的安全,据研究表明160位ECC加密安全性相当于1024位RSA加密,210位ECC加密安全性相当于2048位RSA加密,椭圆曲线在密码学中的使用是1985年由Neal Koblitz和Victor Miller分别独立提出的

算法原理

椭圆曲线加密算法(Elliptic Curve Cryptography,ECC)是一种公钥加密技术,以椭圆曲线理论为基础,利用有限域上椭圆曲线的点构成的Abel群离散对数难解性,实现加密、解密和数字签名,将椭圆曲线中的加法运算与离散对数中的模乘运算相对应就可以建立基于椭圆曲线的对应密码体制

理论基础

域:在一个整数集合中,里面的整数进行加法,减法,乘法,除法产生的结果都在这个集合中,则称这个集合为域

有限域:椭圆曲线是连续的并不适合用于加密,所以必须把椭圆曲线变成离散的点,要把椭圆曲线定义在有限域上,而椭圆曲线密码所使用的椭圆曲线是定义在有限域内,有限域最常见的例子是有限域GF(p),指给定某质数p,由0,1,2...p-1共p个元素组成的整数集合中加法、二倍运算,例如:GF(233)就是

运算规则
加法规则

过曲线上的两点A、B画一条直线,找到直线与椭圆曲线的交点,交点关于x轴对称位置的点,定义为A+B,即为加法,如下图所示:A + B = C

二倍运算

上述方法无法解释A + A,即两点重合的情况,因此在这种情况下取椭圆曲线在A点的切线与椭圆曲线的交点,交点关于x轴对称位置的点,定义为A + A,即2A,即为二倍运算

正负取反

将A关于x轴对称位置的点定义为-A,即椭圆曲线的正负取反运算,如下图所示

无穷远点

如果将A与-A相加,过A与-A的直线平行于y轴,可以认为直线与椭圆曲线相交于无穷远点

综上,定义了A+B、2A运算,因此给定椭圆曲线的某一点G,可以求出2G、3G(即G + 2G)、4G......,即当给定G点时,已知x,求xG点并不困难,反之,已知xG点,求x则非常困难,此即为椭圆曲线加密算法背后的数学原理

主要用途

椭圆曲线加密算法(Elliptic Curve Cryptography,ECC)在区块链中主要用于实现数字资产的安全存储和交易,具体来说它主要用于以下几个方面:

钱包地址生成

区块链中每个用户都有一个唯一的地址用于接收和发送数字资产,该地址是通过椭圆曲线加密算法生成的,通过ECC算法生成的地址具有高度的随机性和不可预测性,能够有效保护用户的数字资产,以下是椭圆曲线加密算法生成钱包地址的详细过程:

  • 选择一个椭圆曲线和一个基点G。在比特币中常用的椭圆曲线是secp256k1,基点G的坐标为(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
  • 选择一个私钥d。私钥是一个256位的随机数,通常表示为一个64位的十六进制字符串,私钥用于生成公钥和签名,必须妥善保管,避免泄露
  • 通过私钥d和基点G计算公钥Q。公钥是一个椭圆曲线上的点,可以表示为(x,y)的坐标形式,在比特币中公钥是一个65字节的字节数组,由04开头,后面跟随64字节的x坐标和64字节的y坐标组成
  • 对公钥进行哈希运算。在比特币中采用SHA-256和RIPEMD-160两个哈希函数对公钥进行哈希运算生成一个20字节的哈希值
  • 添加版本号和校验码。在比特币中钱包地址的版本号为0,校验码是对版本号和哈希值进行两次SHA-256哈希运算后取前4个字节
  • 将版本号、哈希值和校验码组合成一个Base58编码的字符串,得到钱包地址

以下是一个使用Go语言实现椭圆曲线加密算法生成比特币钱包地址的示例代码,该示例代码使用Go语言的crypto/ecdsa包和crypto/elliptic包实现了椭圆曲线加密算法,生成比特币钱包地址,其中base58Encode函数实现了Base58编码算法,用于将版本号、哈希值和校验码组合成一个Base58编码的字符串

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
  "crypto/ecdsa"
  "crypto/elliptic"
  "crypto/rand"
  "crypto/sha256"
  "fmt"
  "golang.org/x/crypto/ripemd160"
  "math/big"
)

func main() {
  // 选择椭圆曲线secp256k1和基点G
  curve := elliptic.P256k1()
  x, _ := new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
  y, _ := new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
  G := ecdsa.PublicKey{Curve: curve, X: x, Y: y}

  // 生成私钥
  privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
  if err != nil {
    fmt.Println("Generate Private Key Error:", err)
    return
  }

  // 生成公钥
  publicKey := privateKey.PublicKey

  // 对公钥进行哈希运算
  publicKeyBytes := elliptic.Marshal(curve, publicKey.X, publicKey.Y)
  hash := sha256.Sum256(publicKeyBytes)
  ripemd160Hasher := ripemd160.New()
  _, err = ripemd160Hasher.Write(hash[:])
  if err != nil {
    fmt.Println("Hash Public Key Error:", err)
    return
  }
  hash160 := ripemd160Hasher.Sum(nil)

  // 添加版本号和校验码
  version := []byte{0}
  payload := append(version, hash160...)
  checksum := sha256.Sum256(sha256.Sum256(payload))
  payload = append(payload, checksum[:4]...)

  // 将版本号、哈希值和校验码组合成一个Base58编码的字符串,得到钱包地址
  address := base58Encode(payload)
  fmt.Println("Address:", address)
}

func base58Encode(payload []byte) string {
  alphabet := "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
  var x big.Int
  x.SetBytes(payload)

  var result []byte
  for x.Cmp(big.NewInt(0)) > 0 {
    mod := new(big.Int)
    x.DivMod(&x, big.NewInt(58), mod)
    result = append(result, alphabet[mod.Int64()])
  }

  for _, b := range payload {
    if b != 0 {
      break
    }
    result = append(result, alphabet[0])
  }

  for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
    result[i], result[j] = result[j], result[i]
  }

  return string(result)
}
签名验证操作

在区块链中每个交易都需要进行数字签名以确保交易的真实性和完整性,这个数字签名是通过私钥对交易数据进行加密生成的,而公钥则用于验证签名,由于ECC算法具有高度的安全性和效率,因此被广泛应用于区块链中的数字签名

下面是椭圆曲线加密算法对交易进行签名验证的详细过程:

  • 选择一个椭圆曲线和一个基点G。在比特币中常用的椭圆曲线是secp256k1,基点G的坐标为(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
  • 选择一个私钥d。私钥是一个256位的随机数,通常表示为一个64位的十六进制字符串,私钥用于生成公钥和签名,必须妥善保管,避免泄露
  • 通过私钥d和基点G计算公钥Q。公钥是一个椭圆曲线上的点,可以表示为(x,y)的坐标形式,在比特币中公钥是一个65字节的字节数组,由04开头,后面跟随64字节的x坐标和64字节的y坐标组成
  • 计算交易的哈希值。在比特币中交易的哈希值是对交易数据进行SHA-256哈希运算后再进行一次RIPEMD-160哈希运算得到的,交易哈希值用于签名和验证
  • 通过私钥d和交易的哈希值计算签名。签名是一个由两个大整数r和s组成的序列,通常表示为一个64字节的字节数组,签名用于验证交易的真实性和完整性
  • 通过公钥Q、交易哈希值和签名验证交易的真实性和完整性。具体来说就是通过公钥Q计算出椭圆曲线上的点P,然后通过签名中的r和s可以计算出椭圆曲线上的点Q,如果点Q和点P相等,则交易验证通过,否则交易验证失败

以下是一个使用Go语言实现椭圆曲线加密算法对比特币交易进行签名验证的示例代码,该示例代码使用Go语言的crypto/ecdsa包和crypto/elliptic包实现了椭圆曲线加密算法对比特币交易进行签名验证,其中ecdsa.Sign函数实现了对交易进行签名的功能,ecdsa.Verify函数实现了对签名进行验证的功能

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
  "crypto/ecdsa"
  "crypto/elliptic"
  "crypto/rand"
  "crypto/sha256"
  "golang.org/x/crypto/ripemd160"
  "math/big"
)

func main() {
  // 选择椭圆曲线secp256k1和基点G
  curve := elliptic.P256k1()
  x, _ := new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
  y, _ := new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
  G := ecdsa.PublicKey{Curve: curve, X: x, Y: y}

  // 生成私钥
  privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
  if err != nil {
    panic(err)
  }

  // 生成公钥
  publicKey := privateKey.PublicKey

  // 生成交易哈希值
  txHash := sha256.Sum256([]byte("Transaction Data"))
  ripemd160Hasher := ripemd160.New()
  _, err = ripemd160Hasher.Write(txHash[:])
  if err != nil {
    panic(err)
  }
  hash160 := ripemd160Hasher.Sum(nil)

  // 签名
  r, s, err := ecdsa.Sign(rand.Reader, privateKey, hash160)
  if err != nil {
    panic(err)
  }
  signature := append(r.Bytes(), s.Bytes()...)

  // 验证签名
  Px, Py := publicKey.Curve.ScalarBaseMult(privateKey.D.Bytes())
  P := ecdsa.PublicKey{Curve: curve, X: Px, Y: Py}
  Qx, Qy := elliptic.Unmarshal(curve, publicKey.X)
  Q := ecdsa.PublicKey{Curve: curve, X: Qx, Y: Qy}
  if !ecdsa.Verify(&P, hash160, new(big.Int).SetBytes(signature[:32]), new(big.Int).SetBytes(signature[32:])) {
    panic("Invalid Signature")
  }
  if !ecdsa.Verify(&Q, hash160, new(big.Int).SetBytes(signature[:32]), new(big.Int).SetBytes(signature[32:])) {
    panic("Invalid Signature")
  }
}
密钥交换实现

椭圆曲线加密算法(Elliptic Curve Cryptography,ECC)可以用于进行密钥交换,实现双方在不泄露私钥的情况下生成共享密钥,以下是椭圆曲线加密算法进行密钥交换的详细过程:

  • 选择一个椭圆曲线和一个基点G。在比特币中常用的椭圆曲线是secp256k1,基点G的坐标为(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
  • 选择一个私钥d1。私钥是一个256位的随机数,通常表示为一个64位的十六进制字符串,私钥用于生成公钥和签名,必须妥善保管,避免泄露
  • 通过私钥d1和基点G计算公钥Q1。公钥是一个椭圆曲线上的点,可以表示为(x,y)的坐标形式,在比特币中公钥是一个65字节的字节数组,由04开头,后面跟随64字节的x坐标和64字节的y坐标组成
  • 选择一个私钥d2。私钥是一个256位的随机数,同样必须妥善保管
  • 通过私钥d2和基点G计算公钥Q2
  • 通过私钥d1和公钥Q2计算共享密钥K。具体来说私钥d1和公钥Q2可以分别表示为d1G和d2G,其中d1和d2都是256位的随机数,共享密钥K可以表示为d1(d2G)或d2(d1G),结果是相同的

以下是一个使用Go语言实现椭圆曲线加密算法进行密钥交换的示例代码,该示例代码使用Go语言的crypto/ecdsa包和crypto/elliptic包实现了椭圆曲线加密算法进行密钥交换,其中curve.ScalarMult函数实现了计算共享密钥的功能,在该示例代码中私钥d1和公钥Q2用于计算共享密钥,结果与使用私钥d2和公钥Q1计算得到的共享密钥相同

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
  "crypto/ecdsa"
  "crypto/elliptic"
  "crypto/rand"
  "fmt"
  "math/big"
)

func main() {
  // 选择椭圆曲线secp256k1和基点G
  curve := elliptic.P256k1()
  x, _ := new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
  y, _ := new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
  G := ecdsa.PublicKey{Curve: curve, X: x, Y: y}

  // 生成私钥d1和公钥Q1
  privateKey1, err := ecdsa.GenerateKey(curve, rand.Reader)
  if err != nil {
    panic(err)
  }
  publicKey1 := privateKey1.PublicKey

  // 生成私钥d2和公钥Q2
  privateKey2, err := ecdsa.GenerateKey(curve, rand.Reader)
  if err != nil {
    panic(err)
  }
  publicKey2 := privateKey2.PublicKey

  // 计算共享密钥
  x, _ = curve.ScalarMult(publicKey2.X, publicKey2.Y, privateKey1.D.Bytes())
  y, _ = curve.ScalarMult(publicKey2.X, publicKey2.Y, privateKey1.D.Bytes())
  K := elliptic.Marshal(curve, x, y)

  fmt.Println(K)
}
默克尔树

默克尔树(Merkle Tree)是一种基于哈希算法的二叉树结构,常用于保证数据的完整性和验证数据的真实性,在区块链技术中默克尔树被广泛应用于保证区块中交易数据的完整性和安全性,默克尔树采用了自底向上的计算方式将相邻的数据进行哈希计算得到哈希值后再将相邻的哈希值进行二两配对,之后继续进行哈希计算直到得到根哈希值为止,这样只要有任何一个数据发生了改变就会导致整个哈希链的哈希值发生改变,从而保证了数据的完整性和安全性

下图是一个Merkle树的示例,该图中会首先会对4个交易记录L1--L4分别计算hash(L1)--hash(L4),然后计算hash0=hash0-0+hash0-1和hash1=hash1-0+hash1-1,最后计算得出根节点的hash值

在以太坊中默克尔树被广泛应用于保证交易信息的完整性和安全性,以太坊中交易数据被组织成一颗默克尔树,每个叶子节点都是一个交易的哈希值,每个非叶子节点都是其子节点哈希值的哈希值,这样只要有任何一个交易发生了改变就会导致整个默克尔树的根哈希值发生改变,从而保证了交易信息的完整性和安全性,下面是以太坊中默克尔树的具体实现示例代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
  "crypto/sha256"
  "encoding/hex"
  "fmt"
)

// 默克尔树节点结构体
type MerkleNode struct {
  Left  *MerkleNode
  Right *MerkleNode
  Data  []byte
}

// 计算节点哈希值
func (node *MerkleNode) calculateHash() []byte {
  if node == nil {
    return nil
  }
  hash := sha256.Sum256(node.Data)
  return hash[:]
}

// 创建新节点
func newMerkleNode(left, right *MerkleNode, data []byte) *MerkleNode {
  node := &MerkleNode{
    Left:  left,
    Right: right,
    Data:  data,
  }
  if left != nil && right != nil {
    hashData := append(left.calculateHash(), right.calculateHash()...)
    node.Data = sha256.Sum256(hashData)[:]
  }
  return node
}

// 创建默克尔树
func newMerkleTree(data [][]byte) *MerkleNode {
  var nodes []*MerkleNode

  for _, datum := range data {
    node := newMerkleNode(nil, nil, datum)
    nodes = append(nodes, node)
  }

  for len(nodes) > 1 {
    var newLevel []*MerkleNode

    for i := 0; i < len(nodes); i += 2 {
      left := nodes[i]
      var right *MerkleNode
      if i+1 < len(nodes) {
        right = nodes[i+1]
      }
      newNode := newMerkleNode(left, right, nil)
      newLevel = append(newLevel, newNode)
    }

    nodes = newLevel
  }

  return nodes[0]
}

// 测试代码
func main() {
  // 创建交易数据
  data := [][]byte{
    []byte("Transaction 1"),
    []byte("Transaction 2"),
    []byte("Transaction 3"),
    []byte("Transaction 4"),
  }

  // 创建默克尔树
  root := newMerkleTree(data)

  // 输出根哈希值
  fmt.Println("Root Hash:", hex.EncodeToString(root.calculateHash()))
}
文末小结

区块链数据结构是区块链技术的核心,它将每个区块链接在一起确保区块链的完整性、安全性和可靠性,区块链数据结构的设计和实现是一个复杂的过程,需要多方面的知识和技能,随着区块链技术的不断发展和普及对区块链数据结构的研究和优化也将成为一个重要的研究方向

参考链接

https://blog.hsm.cool/index.php/archives/679/

https://blog.csdn.net/love131452098/article/details/118198118

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 七芒星实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
jquery操作select(取值,设置选中)
本文由 小马哥 创作,采用 知识共享署名4.0 国际许可协议进行许可 本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
IT小马哥
2023/04/07
4K0
jQuery
    2.jQuery使用户能够更方便地处理HTML Document、Events、实现动画效果、方便地进行Ajax交互,能够极大地简化JavaScript编程。它的宗旨就是:“Write less, do more.“
changxin7
2022/05/06
9.1K0
jQuery
js jquery 基本元素操作
下载:https://github.com/danielm/uploader/archive/master.zip 立即下载
WindWant
2020/09/11
3.5K0
js jquery 基本元素操作
jQuery选择器、元素属性操作--jQuery基础知识点(1)
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
奋飛
2019/08/15
7020
21.jQuery
简介 jQuery是一个快速、简洁的JavaScript框架,jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。jQuery兼容各种主流浏览器,如IE
zhang_derek
2018/04/11
3.1K0
jQuery基础
一、jQuery是什么? jQuery是一个轻量级的、兼容多浏览器的JavaScript库。 jQuery使用户能够更方便地处理HTML Document、Events、实现动画效果、方便地进行Ajax交互,能够极大地简化JavaScript编程。它的宗旨就是:“Write less, do more.“ 二、为什么要用jQuery? 一款轻量级的JS框架。jQuery核心js文件才几十kb,不会影响页面加载速度。 丰富的DOM选择器,jQuery的选择器用起来很方便,比如要找到某个DO
人生不如戏
2018/04/12
2.1K0
Web阶段:第五章:JQuery库
点击:API文档下载 Jquery介绍 1.什么是JQuery ? jQuery,顾名思义,也就是JavaScript和查询(Query),它就是辅助JavaScript开发的js类库。 2.JQue
Java廖志伟
2022/09/28
26.7K0
Web阶段:第五章:JQuery库
jQuery入门基础——选择器
What:jQuery是JavaScript的类库,封装了很多js代码。类似java中的类库一样里面一个类中有很多别人写好的功能。90%以上的公司都在用jQuery。划重点,这句话要考
用户10196776
2022/11/18
10K0
jQuery入门基础——选择器
javaWeb核心技术第五篇之jQuery
- 概述 - jQuery是一个优秀的javascript框架(js类库),兼容css3和各大浏览器,提供dom,events,animate,ajax等简易的操作。并且jQuery有非常丰富的插件,大多数功能都有相应的插件解决方案。jQuery的宗旨是write less, do more. (写的更少,做的更多) - jQuery入门 - jQuery和html整合 - 下载 - 下载地址:www.jquery.com - 使用script的src属性即可
海仔
2019/08/26
8.2K0
jquery操作select(取值,设置选中)
jquery操作select(取值,设置选中) 1. $("#select_id").change(function(){//code...}); //为Select添加事件,当选择其中一项时触发 2. var checkText=$("#select_id").find("option:selected").text(); //获取Select选择的 3. var checkValue=$("#select_id").val(); //获取Select选择的Value 4. var check
程序员同行者
2018/07/02
8.8K0
从零开始学 Web 之 jQuery(四)元素的创建添加与删除,自定义属性
一般 val() 是获取表单的 value 属性; val(值); 设置表单的 value 属性。
Daotin
2018/08/31
2.4K0
从零开始学 Web 之 jQuery(四)元素的创建添加与删除,自定义属性
jquery 操作 select
jQuery获取Select元素,并选择的Text和Value: 1. $("#select_id").change(function(){//code...}); //为Select添加事件,当选择其中一项时触发 2. var checkText=$("#select_id").find("option:selected").text(); //获取Select选择的Text 3. var checkValue=$("#select_id").val(); //获取Select选择的Value 4. var checkIndex=$("#select_id ").get(0).selectedIndex; //获取Select选择的索引值 5. var maxIndex=$("#select_id option:last").attr("index"); //获取Select最大的索引值 jQuery获取Select元素,并设置的 Text和Value: 实例分析: 1. $("#select_id ").get(0).selectedIndex=1; //设置Select索引值为1的项选中 2. $("#select_id ").val(4); // 设置Select的Value值为4的项选中 3. $("#select_id option[text='jQuery']").attr("selected", true); //设置Select的Text值为jQuery的项选中 jQuery添加/删除Select元素的Option项: 实例分析: 1. $("#select_id").append("<option value='Value'>Text</option>"); //为Select追加一个Option(下拉项) 2. $("#select_id").prepend("<option value='0'>请选择</option>"); //为Select插入一个Option(第一个位置) 3. $("#select_id option:last").remove(); //删除Select中索引值最大Option(最后一个) 4. $("#select_id option[index='0']").remove(); //删除Select中索引值为0的Option(第一个) 5. $("#select_id option[value='3']").remove(); //删除Select中Value='3'的Option 6. $("#select_id option[text='4']").remove(); //删除Select中Text='4'的Option 三级分类 <select name="thirdLevel" id="thirdLevel" onchange="getFourthLevel()"> <option value="0" id="thirdOption"> 请选择三级分类 </option> </select> </div> 四级分类: <select name="fourthLevelId" id="fourthLevelId"> <option value="0" id="fourthOption"> 请选择四级分类 </option> </select> </div> .if($("#thirdLevel").val()!=0){ $("#thirdLevel option[value!=0]").remove(); } if($("#fourthLevelId").val()!=0){ $("#fourthLevelId option[value!=0]").remove(); }//这个表示:假如我们希望当选择选择第三类时:如果第四类中有数据则删除,如果没有数据第四类的商品中的为默认值。在后面学习了AJAX技术后经常会使用到!
东营浪人
2019/09/05
1.5K0
京东网页(动态)搭建,利用jquery实现
源代码已分享至本人云盘~~~ 链接:https://pan.baidu.com/s/1Nr5l2Smcmaevs5HHDh5y_A 提取码:blif
时间静止不是简史
2020/07/24
3.5K0
京东网页(动态)搭建,利用jquery实现
jQuery选择器大全(48个代码片段+21幅图演示)
选择器是jQuery最基础的东西,本文中列举的选择器基本上囊括了所有的jQuery选择器,也许各位通过这篇文章能够加深对jQuery选择器的理解,它们本身用法就非常简单,我更希望的是它能够提升个人编写jQuery代码的效率。本文配合截图、代码和简单的概括对所有jQuery选择器进行了介绍,也列举出了一些需要注意和区分的地方。 一、基本选择器 1. id选择器(指定id元素) 将id="one"的元素背景色设置为黑色。(id选择器返单个元素) $(document).ready(function () {
牛嗷嗷
2018/03/30
5.1K0
Jquery简介选择的
Jquery一个js相框(程序代码相结合)这是一个程序开发过程中的半成品;分类似该框架EXTJS。
全栈程序员站长
2022/07/06
1.7K0
前端之jQuery
jQuery对象就是通过jQuery包装DOM对象后产生的对象。jQuery对象是 jQuery独有的。如果一个对象是 jQuery对象,那么它就可以使用jQuery里的方法:例如$(“#i1”).html()。
GH
2019/12/16
5.1K0
Jquery中的CheckBox、RadioButton、DropDownList的取值赋值
$('input:radi0:checked').val(); $("input[type='radi0']:checked").val(); $("input[name='rd']:checked").val();
用户5640963
2019/07/28
1.4K0
jQuery
jQuery jQuery介绍 jQuery 是一个轻量级的、兼容多浏览器的JavaScript 库; jQuery 使用户能够更方便地处理HTML Document、Events、实现动画效果、方便地进行Ajax交互,能够极大地简化JavaScript 编程。它的宗旨就是:Write less,do more.“ jQuery的优势 一款轻量级的JS框架。jQuery核心js文件才几十kb,不会影响页面加载速度。 丰富的DOM选择器,jQuery的选择器用起来很方便,比如要找到某个DOM对象的相邻元素,J
新人小试
2018/04/12
4.8K0
jquery
维护IE678是一件让人头疼的事情,一般我们都会额外加载一个CSS和JS单独处理。值得庆幸的是使用这些浏览器的人也逐步减少,PC端用户已经逐步被移动端用户所取代,如果没有特殊要求的话,一般都会选择放弃对678的支持。
suwanbin
2019/09/26
5.9K0
与Ajax同样重要的jQuery(2)
练习9: ² 点击button 打印radio checkbox select 中选中项的值 <script type="text/javascript" src="../jquery-1.8.3.min.js"></script> <script type="text/javascript"> $(function(){ // 点击button 打印radio checkbox select 中选中项的值 $("#mybutton").click(function(){ // 打印选中性别的值 $("in
Java帮帮
2018/03/19
6.4K0
与Ajax同样重要的jQuery(2)
相关推荐
jquery操作select(取值,设置选中)
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 文章前言
  • 区块结构
  • 哈希算法
  • 椭圆曲线
    • 基本介绍
    • 算法原理
    • 理论基础
    • 运算规则
      • 加法规则
      • 二倍运算
      • 正负取反
      • 无穷远点
    • 主要用途
      • 钱包地址生成
      • 签名验证操作
      • 密钥交换实现
  • 默克尔树
  • 文末小结
  • 参考链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档