Hyperledger Fabric 链代码抛出 MVCC_READ_CONFLICT
Hyperledger Fabric Chaincode throws MVCC_READ_CONFLICT
我在调用链代码函数时遇到错误。我已经为该功能创建了两个改编版本。一个使用常规键,另一个使用复合键。我认为使用复合密钥可以解决任何 MVCC_READ_CONFLICT,因为我不再更新同一个密钥。
但是我在这两个函数上都遇到了错误。请注意,这两个函数都包含在同一个链代码中。不知道会不会引起冲突
这是带有常规键的函数:
func (*AddTokenCallFunction) Start(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 2 {
s := fmt.Sprintf(ERROR_INCORRECT_AMOUNT_OF_ARGUMENTS, "add-tokens", 2, len(args))
return shim.Error(s)
}
account := args[0]
tokens := args[1]
currentTokensBytes, err := stub.GetState(account)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
currentAmountOfTokens := binary.LittleEndian.Uint64(currentTokensBytes)
tokensToAdd, err := strconv.ParseUint(tokens, 10, 64)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
currentAmountOfTokens += tokensToAdd
tokenBytes, err := UintToBytes(currentAmountOfTokens)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
err = stub.PutState(account, tokenBytes)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
return shim.Success(nil)
}
这是相同的函数,但有一个复合键:
func (*AddTokenCompositeCallFunction) Start(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 2 {
s := fmt.Sprintf(ERROR_INCORRECT_AMOUNT_OF_ARGUMENTS, "add-composite-tokens", 2, len(args))
return shim.Error(s)
}
account := args[0]
tokens := args[1]
// Retrieve info needed for the update procedure
txid := stub.GetTxID()
compositeIndexaccount := "account~tokens~txID"
// Create the composite key that will allow us to query for all deltas on a particular variable
compositeKey, compositeErr := stub.CreateCompositeKey(compositeIndexaccount, []string{account, tokens, txid})
if compositeErr != nil {
return shim.Error(fmt.Sprintf("Could not create a composite key for %s: %s", account, compositeErr.Error()))
}
// Save the composite key index
compositePutErr := stub.PutState(compositeKey, []byte{0x00})
if compositePutErr != nil {
return shim.Error(fmt.Sprintf("Could not put operation for %s in the ledger: %s", account, compositePutErr.Error()))
}
return shim.Success([]byte(fmt.Sprintf("Successfully added %s to %s", tokens, account)))
}
有人可以解释为什么我在后来的实施中仍然得到 MVCC_READ_CONFLICT 吗?我究竟做错了什么?我多次进行基准测试并发送相同的 accountID。虽然我的印象是使用复合键时这无关紧要。
提前致谢。
我通过删除自己的实现并将其替换为高吞吐量示例 [https://github.com/hyperledger/fabric-samples/blob/release/high-throughput/chaincode/high-throughput.go] 中的实现解决了这个问题。
我的猜测是我在我的实现中做了一些 Golang 不同意的事情。由于实现方式没有太大区别。
我在调用链代码函数时遇到错误。我已经为该功能创建了两个改编版本。一个使用常规键,另一个使用复合键。我认为使用复合密钥可以解决任何 MVCC_READ_CONFLICT,因为我不再更新同一个密钥。
但是我在这两个函数上都遇到了错误。请注意,这两个函数都包含在同一个链代码中。不知道会不会引起冲突
这是带有常规键的函数:
func (*AddTokenCallFunction) Start(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 2 {
s := fmt.Sprintf(ERROR_INCORRECT_AMOUNT_OF_ARGUMENTS, "add-tokens", 2, len(args))
return shim.Error(s)
}
account := args[0]
tokens := args[1]
currentTokensBytes, err := stub.GetState(account)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
currentAmountOfTokens := binary.LittleEndian.Uint64(currentTokensBytes)
tokensToAdd, err := strconv.ParseUint(tokens, 10, 64)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
currentAmountOfTokens += tokensToAdd
tokenBytes, err := UintToBytes(currentAmountOfTokens)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
err = stub.PutState(account, tokenBytes)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
return shim.Success(nil)
}
这是相同的函数,但有一个复合键:
func (*AddTokenCompositeCallFunction) Start(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 2 {
s := fmt.Sprintf(ERROR_INCORRECT_AMOUNT_OF_ARGUMENTS, "add-composite-tokens", 2, len(args))
return shim.Error(s)
}
account := args[0]
tokens := args[1]
// Retrieve info needed for the update procedure
txid := stub.GetTxID()
compositeIndexaccount := "account~tokens~txID"
// Create the composite key that will allow us to query for all deltas on a particular variable
compositeKey, compositeErr := stub.CreateCompositeKey(compositeIndexaccount, []string{account, tokens, txid})
if compositeErr != nil {
return shim.Error(fmt.Sprintf("Could not create a composite key for %s: %s", account, compositeErr.Error()))
}
// Save the composite key index
compositePutErr := stub.PutState(compositeKey, []byte{0x00})
if compositePutErr != nil {
return shim.Error(fmt.Sprintf("Could not put operation for %s in the ledger: %s", account, compositePutErr.Error()))
}
return shim.Success([]byte(fmt.Sprintf("Successfully added %s to %s", tokens, account)))
}
有人可以解释为什么我在后来的实施中仍然得到 MVCC_READ_CONFLICT 吗?我究竟做错了什么?我多次进行基准测试并发送相同的 accountID。虽然我的印象是使用复合键时这无关紧要。
提前致谢。
我通过删除自己的实现并将其替换为高吞吐量示例 [https://github.com/hyperledger/fabric-samples/blob/release/high-throughput/chaincode/high-throughput.go] 中的实现解决了这个问题。
我的猜测是我在我的实现中做了一些 Golang 不同意的事情。由于实现方式没有太大区别。