fabric中couchdb和leveldb混合使用的问题

fabric中couchdb和leveldb混合使用的问题,第1张

文章目录 背景分析总结

背景

fabric联盟链的同一个通道中,同时使用couchdb和leveldb的peer,在执行多节点背书或者查询时,sdk可能会报错mismatch,两种数据库返回的同一key的查询结果居然不完全相同。

分析

​起初以为是couchdb会自动修改json的字段顺序为字母顺序,当时还在心里大骂couchdb。自己写了一个客户端尝试写入kv到couchdb,查询的结果字段顺序并无变化,只能怀疑是fabric自己做了额外排序。

​果不其然,fabric对json做了unmarshal。因为jsonMap是map[string]interface{},所以重新marshal时,按照字母顺序排序了。

// core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdoc_conv.go

func keyValToCouchDoc(kv *keyValue) (*couchDoc, error) {
	type kvType int32
	const (
		kvTypeDelete = iota
		kvTypeJSON
		kvTypeAttachment
	)
	key, value, metadata, version := kv.key, kv.Value, kv.Metadata, kv.Version
	jsonMap := make(jsonValue)

	var kvtype kvType
	switch {
	case value == nil:
		kvtype = kvTypeDelete
	// check for the case where the jsonMap is nil,  this will indicate
	// a special case for the Unmarshal that results in a valid JSON returning nil
	case json.Unmarshal(value, &jsonMap) == nil && jsonMap != nil:
		kvtype = kvTypeJSON
		if err := jsonMap.checkReservedFieldsNotPresent(); err != nil {
			return nil, err
		}
	default:
		// create an empty map, if the map is nil
		if jsonMap == nil {
			jsonMap = make(jsonValue)
		}
		kvtype = kvTypeAttachment
	}

	verAndMetadata, err := encodeVersionAndMetadata(version, metadata)
	if err != nil {
		return nil, err
	}
	// add the (version + metadata), id, revision, and delete marker (if needed)
	jsonMap[versionField] = verAndMetadata
	jsonMap[idField] = key
	if kv.revision != "" {
		jsonMap[revField] = kv.revision
	}
	if kvtype == kvTypeDelete {
		jsonMap[deletedField] = true
	}
	jsonBytes, err := jsonMap.toBytes()
	if err != nil {
		return nil, err
	}
	couchDoc := &couchDoc{jsonValue: jsonBytes}
	if kvtype == kvTypeAttachment {
		attachment := &attachmentInfo{}
		attachment.AttachmentBytes = value
		attachment.ContentType = "application/octet-stream"
		attachment.Name = binaryWrapper
		attachments := append([]*attachmentInfo{}, attachment)
		couchDoc.attachments = attachments
	}
	return couchDoc, nil
}
总结

不同语言marshal的json字段顺序也往往不一致,所以fabric网络不同组织如果混用不同语言实现的同一个业务合约,可能会遇到类似的麻烦,解决方案也很简单,可以在sdk层做一下json字段的重排。
目前截止fabric2.2.x这个最新的LTS版本都有这个问题,但是新版的fabric已经在修复此问题,详见

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/928667.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-17
下一篇2022-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存