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

文章目录

背景

在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已经在修复此问题,详见

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值