文档库 最新最全的文档下载
当前位置:文档库 › 兄弟连Go语言区块链培训教程之以太坊源码详解2

兄弟连Go语言区块链培训教程之以太坊源码详解2

兄弟连Go语言区块链培训教程之以太坊源码详解2
兄弟连Go语言区块链培训教程之以太坊源码详解2

很多人喜欢Go语言,其实是因为Go语言有其独特的语言属性在支撑着其在编程语言界的发展,今天兄弟连Go语言+区块链培训老师给大家介绍一下关于以太坊源码详解2,下面我们一起来看一下吧。

接下来我们看一下RLP,RLP是一种编码规则,以太坊中的数据都会经过它编码之后才会存储到数据库中,如下图

()

上面是RLP的编码原理,接下来我们看一下以太坊中的RLP

()

从图上我们可以看到,在以太坊源码中,RLP包里面有用的文件其实只有三个,接下来我们详细看看

typecache.go:

1. 核心数据结构

核心数据结构

var (

typeCacheMutex sync.RWMutex typeCache=make(map[typekey]*typeinfo)

)

type typeinfo struct {

decoder

writer

}

type typekey struct {

reflect.Type

// the key must include the struct tags because they // might generate a different decoder.

tags

}

核心函数

// map的查询

func cachedTypeInfo(typ reflect.Type, tags tags) (*typeinfo, error) { // 加锁

typeCacheMutex.RLock()

info := typeCache[typekey{typ, tags}] // 查找类型

typeCacheMutex.RUnlock() // 解锁

if info != nil { // 如果不为空,直接返回

return info, nil

}

// not in the cache, need to generate info for this type.

typeCacheMutex.Lock()

defer typeCacheMutex.Unlock()

return cachedTypeInfo1(typ, tags)

}

func cachedTypeInfo1(typ reflect.Type, tags tags) (*typeinfo, error) {

key := typekey{typ, tags}

info := typeCache[key]

if info != nil {

// 不为空,有可能是别的goroutine已经创建成功了,直接获取信息,返回

// another goroutine got the write lock first

return info, nil

}

// put a dummmy value into the cache before generating.

// if the generator tries to lookup itself, it will get

// the dummy value and won't call itself recursively.

// 创建了一个值来填充这个类型的位置,避免遇到一些递归定义是产生死循环

typeCache[key] = new(typeinfo)

info, err := genTypeInfo(typ, tags)

if err != nil {

// remove the dummy value if the generator fails

delete(typeCache, key)

return nil, err

}

*typeCache[key] = *info //存储到缓存中

return typeCache[key], err

}

生成对应的编码/解码器函数

// 生成对应类型的编、解码器函数

func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err er ror) {

info = new(typeinfo)

// 创建解码器

if info.decoder, err = makeDecoder(typ, tags); err != nil {

return nil, err

}

// 创建编码器

if info.writer, err = makeWriter(typ); err != nil {

return nil, err

}

return info, nil

}

上面是typecache.go中的主要逻辑

encode.go

编码器

1 .核心数据结构

var (

// Common encoded values.

// These are useful when implementing EncodeRLP.

EmptyString = []byte{0x80}

EmptyList = []byte{0xC0}

)

// Encoder is implemented by types that require custom

// encoding rules or want to encode private fields.

type Encoder interface {

// EncodeRLP should write the RLP encoding o f its receiver to w.

// If the implementation is a pointer method, i t may also be

// called for nil pointers.

//

// Implementations should generate valid RLP. The data written is

// not verified at the moment, but a future v ersion might. It is

// recommended to write only a single value but writing multiple

???? encode.go

// values or no value at all is also permi tted.

EncodeRLP(io.Writer) error // 接口类型

}

2 .编码

func Encode(w io.Writer, val interface{}) error {

if outer, ok := w.(*encbuf); ok {

// Encode was called by some t ype's EncodeRLP.

// Avoid copying by writing to t he outer encbuf directly.

return outer.encode(val)

}

eb := encbufPool.Get().(*encbuf)

defer encbufPool.Put(eb)

eb.reset()

if err := eb.encode(val); err != nil {

return err

}

return eb.toWriter(w)

}

func (w *encbuf) encode(val interface{}) error {

rval := reflect.ValueOf(val)

ti, err := cachedTypeInfo(rval.Type(), tags{})

if err != nil {

return err

}

return ti.writer(rval, w)

}

// 此处充当buffer

type encbuf struct {

str []byte //string data, contains everything except list headers

lheads []*listhead // all list headers

lhsize int // sum of sizes of all encoded list headers

sizebuf []byte // 9-byte auxiliary buffer for uint encod ing

}

type listhead struct{

offset int // index of this header in string data

size int // total size of encoded data (including list h eaders)

}

上面是编码器的核心函数,解码的逻辑大致一样,我们不再多说

相关文档