-
Notifications
You must be signed in to change notification settings - Fork 0
/
proof.go
67 lines (55 loc) · 2.06 KB
/
proof.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package proof
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/KYVENetwork/trustless-client-go/types"
"github.com/KYVENetwork/trustless-client-go/utils"
)
var (
logger = utils.TrustlessClientLogger("proof")
)
// DataItemInclusionProof proves the validity of a given Data Item.
// Therefore, it regenerates the Merkle root with the provided Merkle nodes in order to
// compare the locally computed hash with the one stored on-chain.
// It returns true if the given Data Item is the actually validated one by KYVE and false if not.
func DataItemInclusionProof(trustlessDataItem types.TrustlessDataItem, endpoint string) error {
// 1. Check if Merkle leaf in proof matches hash of local data item
leafHash := sha256.Sum256(trustlessDataItem.Value)
var parentHash [32]byte
for _, merkleNode := range trustlessDataItem.Proof {
nodeHash, err := hex.DecodeString(merkleNode.Hash)
if err != nil {
return fmt.Errorf("failed to decode Merkle node hash: %v", err)
}
if merkleNode.Left {
combined := append(leafHash[:], nodeHash[:]...)
parentHash = sha256.Sum256(combined)
} else {
combined := append(nodeHash[:], leafHash[:]...)
parentHash = sha256.Sum256(combined)
}
leafHash = parentHash
}
merkleRoot := hex.EncodeToString(parentHash[:])
// 2. Compare local Merkle root with Merkle root stored on-chain
restEndpoint := utils.GetChainRest(trustlessDataItem.ChainId, endpoint)
bundle, err := utils.GetFinalizedBundle(restEndpoint, trustlessDataItem.PoolId, trustlessDataItem.BundleId)
if err != nil {
logger.Error().Str("err", err.Error()).Msg("Failed to get finalized bundle")
return err
}
var bundleSummary *types.BundleSummary
if err = json.Unmarshal([]byte(bundle.BundleSummary), &bundleSummary); err != nil {
return fmt.Errorf("failed to unmarshal bundle summary: %v", err)
}
if bundleSummary.MerkleRoot != merkleRoot {
logger.Fatal().Msg("Mismatch: Local Merkle root != Chain Merkle root")
return types.MerkleRootNotValidError{
OnChain: bundleSummary.MerkleRoot,
Constructed: merkleRoot,
}
}
return nil
}