Search code examples
couchdbhyperledger-fabrichyperledger

Hyperledger fabric Ledger and couchdb Problem


I am confused by how hyperledger fabric stores data .After I read the offical doc,I know there are two parts in Ledger: WORLD_STATE and BLOCKCHAIN . I start a fabric network in my computer with couchdb , using command like : ./network.sh createChannel -ca -s couchdb, and init some data stored in Ledger.
But there is my confued:

  1. if I change the data directly in couchdb like : http://localhost:port/_utils/ , I found that query result also changed when i using command : peer chaincode query -C mychannel -n CC_NAME -c '{"Args":["QueryAll"]}',is that means anyone can change the ledger without approved by half of all peers?
  2. I am using golang to wirte the code, the queryAll is like:
    os.Setenv("DISCOVERY_AS_LOCALHOST", "true")
    wallet, err := gateway.NewFileSystemWallet("wallet")
    if err != nil {
        fmt.Printf("ERROR:%s\n", err)
        os.Exit(1)
    }
    if !wallet.Exists("appUser") {
        err = populateWallet(wallet)
        if err != nil {
            fmt.Printf("Wallet wrong : %s\n", err)
            os.Exit(1)
        }
    }

    ccpPath := filepath.Join(
        "..",
        "..",
        "network",
        "organizations",
        "peerOrganizations",
        "org1.example.com",
        "connection-org1.yaml",
        )

    gw, err := gateway.Connect(
        gateway.WithConfig(config.FromFile(filepath.Clean(ccpPath))),
        gateway.WithIdentity(wallet, "appUser"),
        )
    if err != nil {
        fmt.Printf("failed to connect to net : %s\n", err)
        os.Exit(1)
    }
    defer gw.Close()

    network, err := gw.GetNetwork("mychannel")
    if err != nil {
        fmt.Printf("%s\n", err)
        os.Exit(1)
    }
    fmt.Println("Start to query all")
    contract := network.GetContract("project_test")

    result, err := contract.EvaluateTransaction("queryAllMessage")
    if err != nil {
        fmt.Printf("ERROR:%s\n", err)
        os.Exit(1)
    }
    fmt.Println(string(result))

I found that After i change the data directly in couchdb, it can't run and the error is like:

Failed to evaluate: endorsement validation failed: Endorser Client Status Code: (3) ENDORSEMENT_MISMATCH. Description: ProposalResponsePayloads do not match exit status 1 It seems doesn't work if one changed his couchdb .

I want to know why these happend ,and how can I avoid others change database , how can I make sure that the data i get is approved by all peers ? any help could be useful ,thank you.


Solution

  • Each peer has its own CouchDB DB. That DB is the one that stores the ledger's world state, so, if you change data directly on the DB the world state of that specific peer it's gonna change. But this way you are not tampering the world state of the channel in the Fabric network. You are breaking the state of the peer. That specific peer is gonna return the wrong (altered) state. But the other peers are going to return the good one. When that peer performs and endorsement, it is going to mismatch from the endorsements from other peers, so the endorsement will fail (and that is what is happening to you later). In a blockchain network, if you don't agree the consensus you are out of the network.

    1. No. You have broken the world state of that peer. The channel ledger of the Fabric network (and thus, the rest of the peers) remains the same. You need to accomplish with the Fabric transaction flow, which require to fulfill the endorsement policy. The responses from the altered peers are no more valid.

    2. Your peer's state has been tampered. Thus, its endorsement does not match the one from untampered peers, as it is expected to. Even if your endorsement policy requires endorsement from only one peer, the other peers are going to detect a mismatch in the readset/writeset version when trying to commit.

    Thus, it is working as expected. You are not allowed to tamper the state directly from CouchDB. You are simply breaking the state of the peer. It is the responsibility of the system administrator of the corresponding organization to provide measures to avoid breaking the state of the peer.

    Anyway you can always clear the ledger of the tampered peer (chain + state) and make it synchronize with the network again.