diff --git a/go/ics23.go b/go/ics23.go index 76db0681..1950c877 100644 --- a/go/ics23.go +++ b/go/ics23.go @@ -52,7 +52,7 @@ func VerifyMembership(spec *ProofSpec, root CommitmentRoot, proof *CommitmentPro func VerifyNonMembership(spec *ProofSpec, root CommitmentRoot, proof *CommitmentProof, key []byte) bool { // decompress it before running code (no-op if not compressed) proof = Decompress(proof) - np := getNonExistProofForKey(proof, key) + np := getNonExistProofForKey(spec, proof, key) if np == nil { return false } @@ -148,16 +148,16 @@ func getExistProofForKey(proof *CommitmentProof, key []byte) *ExistenceProof { return nil } -func getNonExistProofForKey(proof *CommitmentProof, key []byte) *NonExistenceProof { +func getNonExistProofForKey(spec *ProofSpec, proof *CommitmentProof, key []byte) *NonExistenceProof { switch p := proof.Proof.(type) { case *CommitmentProof_Nonexist: np := p.Nonexist - if isLeft(np.Left, key) && isRight(np.Right, key) { + if isLeft(spec, np.Left, key) && isRight(spec, np.Right, key) { return np } case *CommitmentProof_Batch: for _, sub := range p.Batch.Entries { - if np := sub.GetNonexist(); np != nil && isLeft(np.Left, key) && isRight(np.Right, key) { + if np := sub.GetNonexist(); np != nil && isLeft(spec, np.Left, key) && isRight(spec, np.Right, key) { return np } } @@ -165,10 +165,10 @@ func getNonExistProofForKey(proof *CommitmentProof, key []byte) *NonExistencePro return nil } -func isLeft(left *ExistenceProof, key []byte) bool { - return left == nil || bytes.Compare(left.Key, key) < 0 +func isLeft(spec *ProofSpec, left *ExistenceProof, key []byte) bool { + return left == nil || bytes.Compare(keyForComparison(spec, left.Key), keyForComparison(spec, key)) < 0 } -func isRight(right *ExistenceProof, key []byte) bool { - return right == nil || bytes.Compare(right.Key, key) > 0 +func isRight(spec *ProofSpec, right *ExistenceProof, key []byte) bool { + return right == nil || bytes.Compare(keyForComparison(spec, right.Key), keyForComparison(spec, key)) > 0 } diff --git a/go/proof.go b/go/proof.go index 44fc0034..535b3cd8 100644 --- a/go/proof.go +++ b/go/proof.go @@ -47,7 +47,7 @@ var TendermintSpec = &ProofSpec{ var SmtSpec = &ProofSpec{ LeafSpec: &LeafOp{ Hash: HashOp_SHA256, - PrehashKey: HashOp_NO_HASH, + PrehashKey: HashOp_SHA256, PrehashValue: HashOp_SHA256, Length: LengthOp_NO_PREFIX, Prefix: []byte{0}, @@ -60,7 +60,8 @@ var SmtSpec = &ProofSpec{ EmptyChild: make([]byte, 32), Hash: HashOp_SHA256, }, - MaxDepth: 256, + MaxDepth: 256, + PrehashKeyBeforeComparison: true, } func encodeVarintProto(l int) []byte { @@ -204,6 +205,17 @@ func (p *ExistenceProof) CheckAgainstSpec(spec *ProofSpec) error { return nil } +// If we should prehash the key before comparison, do so; otherwise, return the key. Prehashing +// changes lexical comparison, so we do so before comparison if the spec sets +// `PrehashKeyBeforeComparison`. +func keyForComparison(spec *ProofSpec, key []byte) []byte { + if !spec.PrehashKeyBeforeComparison { + return key + } + hash, _ := doHashOrNoop(spec.LeafSpec.PrehashKey, key) + return hash +} + // Verify does all checks to ensure the proof has valid non-existence proofs, // and they ensure the given key is not in the CommitmentState func (p *NonExistenceProof) Verify(spec *ProofSpec, root CommitmentRoot, key []byte) error { @@ -229,13 +241,13 @@ func (p *NonExistenceProof) Verify(spec *ProofSpec, root CommitmentRoot, key []b // Ensure in valid range if rightKey != nil { - if bytes.Compare(key, rightKey) >= 0 { + if bytes.Compare(keyForComparison(spec, key), keyForComparison(spec, rightKey)) >= 0 { return errors.New("key is not left of right proof") } } if leftKey != nil { - if bytes.Compare(key, leftKey) <= 0 { + if bytes.Compare(keyForComparison(spec, key), keyForComparison(spec, leftKey)) <= 0 { return errors.New("key is not right of left proof") } } diff --git a/go/proofs.pb.go b/go/proofs.pb.go index a973dcf8..c79b9502 100644 --- a/go/proofs.pb.go +++ b/go/proofs.pb.go @@ -63,11 +63,11 @@ func (HashOp) EnumDescriptor() ([]byte, []int) { return fileDescriptor_855156e15e7b8e99, []int{0} } -//* -//LengthOp defines how to process the key and value of the LeafOp -//to include length information. After encoding the length with the given -//algorithm, the length will be prepended to the key and value bytes. -//(Each one with it's own encoded length) +// * +// LengthOp defines how to process the key and value of the LeafOp +// to include length information. After encoding the length with the given +// algorithm, the length will be prepended to the key and value bytes. +// (Each one with it's own encoded length) type LengthOp int32 const ( @@ -123,26 +123,26 @@ func (LengthOp) EnumDescriptor() ([]byte, []int) { return fileDescriptor_855156e15e7b8e99, []int{1} } -//* -//ExistenceProof takes a key and a value and a set of steps to perform on it. -//The result of peforming all these steps will provide a "root hash", which can -//be compared to the value in a header. +// * +// ExistenceProof takes a key and a value and a set of steps to perform on it. +// The result of peforming all these steps will provide a "root hash", which can +// be compared to the value in a header. // -//Since it is computationally infeasible to produce a hash collission for any of the used -//cryptographic hash functions, if someone can provide a series of operations to transform -//a given key and value into a root hash that matches some trusted root, these key and values -//must be in the referenced merkle tree. +// Since it is computationally infeasible to produce a hash collission for any of the used +// cryptographic hash functions, if someone can provide a series of operations to transform +// a given key and value into a root hash that matches some trusted root, these key and values +// must be in the referenced merkle tree. // -//The only possible issue is maliablity in LeafOp, such as providing extra prefix data, -//which should be controlled by a spec. Eg. with lengthOp as NONE, -//prefix = FOO, key = BAR, value = CHOICE -//and -//prefix = F, key = OOBAR, value = CHOICE -//would produce the same value. +// The only possible issue is maliablity in LeafOp, such as providing extra prefix data, +// which should be controlled by a spec. Eg. with lengthOp as NONE, +// prefix = FOO, key = BAR, value = CHOICE +// and +// prefix = F, key = OOBAR, value = CHOICE +// would produce the same value. // -//With LengthOp this is tricker but not impossible. Which is why the "leafPrefixEqual" field -//in the ProofSpec is valuable to prevent this mutability. And why all trees should -//length-prefix the data before hashing it. +// With LengthOp this is tricker but not impossible. Which is why the "leafPrefixEqual" field +// in the ProofSpec is valuable to prevent this mutability. And why all trees should +// length-prefix the data before hashing it. type ExistenceProof struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` @@ -211,10 +211,9 @@ func (m *ExistenceProof) GetPath() []*InnerOp { return nil } -// -//NonExistenceProof takes a proof of two neighbors, one left of the desired key, -//one right of the desired key. If both proofs are valid AND they are neighbors, -//then there is no valid proof for the given key. +// NonExistenceProof takes a proof of two neighbors, one left of the desired key, +// one right of the desired key. If both proofs are valid AND they are neighbors, +// then there is no valid proof for the given key. type NonExistenceProof struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Left *ExistenceProof `protobuf:"bytes,2,opt,name=left,proto3" json:"left,omitempty"` @@ -275,10 +274,10 @@ func (m *NonExistenceProof) GetRight() *ExistenceProof { return nil } -// -//CommitmentProof is either an ExistenceProof or a NonExistenceProof, or a Batch of such messages +// CommitmentProof is either an ExistenceProof or a NonExistenceProof, or a Batch of such messages type CommitmentProof struct { // Types that are valid to be assigned to Proof: + // // *CommitmentProof_Exist // *CommitmentProof_Nonexist // *CommitmentProof_Batch @@ -388,21 +387,21 @@ func (*CommitmentProof) XXX_OneofWrappers() []interface{} { } } -//* -//LeafOp represents the raw key-value data we wish to prove, and -//must be flexible to represent the internal transformation from -//the original key-value pairs into the basis hash, for many existing -//merkle trees. +// * +// LeafOp represents the raw key-value data we wish to prove, and +// must be flexible to represent the internal transformation from +// the original key-value pairs into the basis hash, for many existing +// merkle trees. // -//key and value are passed in. So that the signature of this operation is: -//leafOp(key, value) -> output +// key and value are passed in. So that the signature of this operation is: +// leafOp(key, value) -> output // -//To process this, first prehash the keys and values if needed (ANY means no hash in this case): -//hkey = prehashKey(key) -//hvalue = prehashValue(value) +// To process this, first prehash the keys and values if needed (ANY means no hash in this case): +// hkey = prehashKey(key) +// hvalue = prehashValue(value) // -//Then combine the bytes, and hash it -//output = hash(prefix || length(hkey) || hkey || length(hvalue) || hvalue) +// Then combine the bytes, and hash it +// output = hash(prefix || length(hkey) || hkey || length(hvalue) || hvalue) type LeafOp struct { Hash HashOp `protobuf:"varint,1,opt,name=hash,proto3,enum=ics23.HashOp" json:"hash,omitempty"` PrehashKey HashOp `protobuf:"varint,2,opt,name=prehash_key,json=prehashKey,proto3,enum=ics23.HashOp" json:"prehash_key,omitempty"` @@ -481,22 +480,22 @@ func (m *LeafOp) GetPrefix() []byte { return nil } -//* -//InnerOp represents a merkle-proof step that is not a leaf. -//It represents concatenating two children and hashing them to provide the next result. +// * +// InnerOp represents a merkle-proof step that is not a leaf. +// It represents concatenating two children and hashing them to provide the next result. // -//The result of the previous step is passed in, so the signature of this op is: -//innerOp(child) -> output +// The result of the previous step is passed in, so the signature of this op is: +// innerOp(child) -> output // -//The result of applying InnerOp should be: -//output = op.hash(op.prefix || child || op.suffix) +// The result of applying InnerOp should be: +// output = op.hash(op.prefix || child || op.suffix) // -//where the || operator is concatenation of binary data, -//and child is the result of hashing all the tree below this step. +// where the || operator is concatenation of binary data, +// and child is the result of hashing all the tree below this step. // -//Any special data, like prepending child with the length, or prepending the entire operation with -//some value to differentiate from leaf nodes, should be included in prefix and suffix. -//If either of prefix or suffix is empty, we just treat it as an empty string +// Any special data, like prepending child with the length, or prepending the entire operation with +// some value to differentiate from leaf nodes, should be included in prefix and suffix. +// If either of prefix or suffix is empty, we just treat it as an empty string type InnerOp struct { Hash HashOp `protobuf:"varint,1,opt,name=hash,proto3,enum=ics23.HashOp" json:"hash,omitempty"` Prefix []byte `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty"` @@ -557,17 +556,17 @@ func (m *InnerOp) GetSuffix() []byte { return nil } -//* -//ProofSpec defines what the expected parameters are for a given proof type. -//This can be stored in the client and used to validate any incoming proofs. +// * +// ProofSpec defines what the expected parameters are for a given proof type. +// This can be stored in the client and used to validate any incoming proofs. // -//verify(ProofSpec, Proof) -> Proof | Error +// verify(ProofSpec, Proof) -> Proof | Error // -//As demonstrated in tests, if we don't fix the algorithm used to calculate the -//LeafHash for a given tree, there are many possible key-value pairs that can -//generate a given hash (by interpretting the preimage differently). -//We need this for proper security, requires client knows a priori what -//tree format server uses. But not in code, rather a configuration object. +// As demonstrated in tests, if we don't fix the algorithm used to calculate the +// LeafHash for a given tree, there are many possible key-value pairs that can +// generate a given hash (by interpretting the preimage differently). +// We need this for proper security, requires client knows a priori what +// tree format server uses. But not in code, rather a configuration object. type ProofSpec struct { // any field in the ExistenceProof must be the same as in this spec. // except Prefix, which is just the first bytes of prefix (spec can be longer) @@ -577,6 +576,10 @@ type ProofSpec struct { MaxDepth int32 `protobuf:"varint,3,opt,name=max_depth,json=maxDepth,proto3" json:"max_depth,omitempty"` // min_depth (if > 0) is the minimum number of InnerOps allowed (mainly for fixed-depth tries) MinDepth int32 `protobuf:"varint,4,opt,name=min_depth,json=minDepth,proto3" json:"min_depth,omitempty"` + // prehash_key_before_comparison is a flag that indicates whether to use the + // prehash_key specified by LeafOp to compare lexical ordering of keys for + // non-existence proofs. + PrehashKeyBeforeComparison bool `protobuf:"varint,5,opt,name=prehash_key_before_comparison,json=prehashKeyBeforeComparison,proto3" json:"prehash_key_before_comparison,omitempty"` } func (m *ProofSpec) Reset() { *m = ProofSpec{} } @@ -640,15 +643,21 @@ func (m *ProofSpec) GetMinDepth() int32 { return 0 } +func (m *ProofSpec) GetPrehashKeyBeforeComparison() bool { + if m != nil { + return m.PrehashKeyBeforeComparison + } + return false +} + +// InnerSpec contains all store-specific structure info to determine if two proofs from a +// given store are neighbors. // -//InnerSpec contains all store-specific structure info to determine if two proofs from a -//given store are neighbors. -// -//This enables: +// This enables: // -//isLeftMost(spec: InnerSpec, op: InnerOp) -//isRightMost(spec: InnerSpec, op: InnerOp) -//isLeftNeighbor(spec: InnerSpec, left: InnerOp, right: InnerOp) +// isLeftMost(spec: InnerSpec, op: InnerOp) +// isRightMost(spec: InnerSpec, op: InnerOp) +// isLeftNeighbor(spec: InnerSpec, left: InnerOp, right: InnerOp) type InnerSpec struct { // Child order is the ordering of the children node, must count from 0 // iavl tree is [0, 1] (left then right) @@ -738,8 +747,7 @@ func (m *InnerSpec) GetHash() HashOp { return HashOp_NO_HASH } -// -//BatchProof is a group of multiple proof types than can be compressed +// BatchProof is a group of multiple proof types than can be compressed type BatchProof struct { Entries []*BatchEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` } @@ -787,6 +795,7 @@ func (m *BatchProof) GetEntries() []*BatchEntry { // Use BatchEntry not CommitmentProof, to avoid recursion type BatchEntry struct { // Types that are valid to be assigned to Proof: + // // *BatchEntry_Exist // *BatchEntry_Nonexist Proof isBatchEntry_Proof `protobuf_oneof:"proof"` @@ -925,6 +934,7 @@ func (m *CompressedBatchProof) GetLookupInners() []*InnerOp { // Use BatchEntry not CommitmentProof, to avoid recursion type CompressedBatchEntry struct { // Types that are valid to be assigned to Proof: + // // *CompressedBatchEntry_Exist // *CompressedBatchEntry_Nonexist Proof isCompressedBatchEntry_Proof `protobuf_oneof:"proof"` @@ -1158,66 +1168,68 @@ func init() { func init() { proto.RegisterFile("proofs.proto", fileDescriptor_855156e15e7b8e99) } var fileDescriptor_855156e15e7b8e99 = []byte{ - // 940 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4b, 0x6f, 0xe3, 0x54, - 0x14, 0xce, 0x4d, 0x62, 0x27, 0x39, 0x69, 0x53, 0xf7, 0xaa, 0x20, 0x4b, 0x15, 0x69, 0xf1, 0x86, - 0x4e, 0x47, 0x14, 0x26, 0x99, 0x06, 0xb1, 0x40, 0xa2, 0x49, 0x3d, 0xc4, 0x6a, 0x69, 0xc2, 0x4d, - 0x18, 0x0d, 0x12, 0x92, 0xe5, 0x49, 0x6f, 0x26, 0xd6, 0x24, 0xb6, 0x65, 0xbb, 0x28, 0x19, 0x81, - 0x90, 0xf8, 0x05, 0xac, 0x61, 0xc7, 0x96, 0x3f, 0xc2, 0xb2, 0x4b, 0x96, 0xa8, 0x5d, 0xb0, 0xe0, - 0x4f, 0xa0, 0xfb, 0x88, 0x9b, 0x27, 0xed, 0x02, 0xcd, 0xee, 0x9e, 0xef, 0x7c, 0xe7, 0x71, 0xcf, - 0xc3, 0xd7, 0xb0, 0x11, 0x84, 0xbe, 0xdf, 0x8f, 0x8e, 0x82, 0xd0, 0x8f, 0x7d, 0xac, 0xb8, 0xbd, - 0xa8, 0x52, 0x35, 0x7e, 0x84, 0x92, 0x39, 0x76, 0xa3, 0x98, 0x7a, 0x3d, 0xda, 0x66, 0x7a, 0xac, - 0x41, 0xe6, 0x35, 0x9d, 0xe8, 0x68, 0x1f, 0x1d, 0x6c, 0x10, 0x76, 0xc4, 0x3b, 0xa0, 0x7c, 0xe7, - 0x0c, 0xaf, 0xa8, 0x9e, 0xe6, 0x98, 0x10, 0xf0, 0xfb, 0x90, 0x1d, 0x52, 0xa7, 0xaf, 0x67, 0xf6, - 0xd1, 0x41, 0xb1, 0xb2, 0x79, 0xc4, 0xfd, 0x1d, 0x9d, 0x53, 0xa7, 0xdf, 0x0a, 0x08, 0x57, 0x61, - 0x03, 0xb2, 0x81, 0x13, 0x0f, 0xf4, 0xec, 0x7e, 0xe6, 0xa0, 0x58, 0x29, 0x49, 0x8a, 0xe5, 0x79, - 0x34, 0x64, 0x1c, 0xa6, 0x33, 0x7e, 0x80, 0xed, 0x0b, 0xdf, 0xbb, 0x37, 0x87, 0x47, 0x2c, 0x5a, - 0x3f, 0xe6, 0x29, 0x14, 0x2b, 0xef, 0x48, 0x57, 0xf3, 0x66, 0x84, 0x53, 0xf0, 0x63, 0x50, 0x42, - 0xf7, 0xd5, 0x20, 0x96, 0x99, 0xad, 0xe1, 0x0a, 0x8e, 0xf1, 0x0f, 0x82, 0xad, 0x86, 0x3f, 0x1a, - 0xb9, 0xf1, 0x88, 0x7a, 0xb1, 0x88, 0xfe, 0x21, 0x28, 0x94, 0x91, 0x79, 0xfc, 0x75, 0x0e, 0x9a, - 0x29, 0x22, 0x58, 0xb8, 0x06, 0x79, 0xcf, 0xf7, 0x84, 0x85, 0x48, 0x4f, 0x97, 0x16, 0x4b, 0x17, - 0x6b, 0xa6, 0x48, 0xc2, 0xc5, 0x8f, 0x40, 0x79, 0xe9, 0xc4, 0xbd, 0x81, 0xcc, 0x73, 0x5b, 0x1a, - 0xd5, 0x19, 0x96, 0x84, 0xe0, 0x0c, 0xfc, 0x19, 0x40, 0xcf, 0x1f, 0x05, 0x21, 0x8d, 0x22, 0x7a, - 0xa9, 0x67, 0x39, 0x7f, 0x57, 0xf2, 0x1b, 0x89, 0x62, 0xce, 0x72, 0xc6, 0xa0, 0x9e, 0x03, 0x85, - 0xf7, 0xde, 0xb8, 0x46, 0xa0, 0x8a, 0x0e, 0xb1, 0xf6, 0x0d, 0x9c, 0x68, 0xc0, 0xef, 0x58, 0x4a, - 0xda, 0xd7, 0x74, 0xa2, 0x01, 0x6b, 0x0d, 0x53, 0xe1, 0x23, 0x28, 0x06, 0x21, 0x65, 0x47, 0x9b, - 0x75, 0x23, 0xbd, 0x8a, 0x09, 0x92, 0x71, 0x46, 0x27, 0xb8, 0x02, 0x9b, 0x53, 0xbe, 0x98, 0x97, - 0xcc, 0x2a, 0x8b, 0x0d, 0xc9, 0x79, 0xce, 0xa7, 0xe8, 0x03, 0x50, 0x87, 0xd4, 0x7b, 0xc5, 0x87, - 0x84, 0x91, 0xb7, 0x92, 0x39, 0x62, 0x60, 0x2b, 0x20, 0x52, 0x8d, 0xdf, 0x05, 0x35, 0x08, 0x69, - 0xdf, 0x1d, 0xeb, 0x0a, 0x9f, 0x0a, 0x29, 0x19, 0xdf, 0x42, 0x4e, 0x0e, 0xd4, 0x43, 0xae, 0x74, - 0xe7, 0x25, 0x3d, 0xeb, 0x85, 0xe1, 0xd1, 0x55, 0x9f, 0xe1, 0x19, 0x81, 0x0b, 0xc9, 0xf8, 0x0d, - 0x41, 0x81, 0x57, 0xb4, 0x13, 0xd0, 0x1e, 0x3e, 0x84, 0x02, 0x9b, 0x6b, 0x3b, 0x0a, 0x68, 0x4f, - 0x0e, 0xc7, 0xc2, 0xdc, 0xe7, 0x99, 0x9e, 0x73, 0x3f, 0x02, 0x70, 0x59, 0x5e, 0x82, 0x2c, 0xe6, - 0x42, 0x9b, 0xdd, 0x00, 0xc6, 0x22, 0x05, 0x77, 0x7a, 0xc4, 0xbb, 0x50, 0x18, 0x39, 0x63, 0xfb, - 0x92, 0x06, 0xb1, 0x18, 0x09, 0x85, 0xe4, 0x47, 0xce, 0xf8, 0x94, 0xc9, 0x5c, 0xe9, 0x7a, 0x52, - 0x99, 0x95, 0x4a, 0xd7, 0xe3, 0x4a, 0xe3, 0x6f, 0x04, 0x85, 0xc4, 0x25, 0xde, 0x83, 0x62, 0x6f, - 0xe0, 0x0e, 0x2f, 0x6d, 0x3f, 0xbc, 0xa4, 0xa1, 0x8e, 0xf6, 0x33, 0x07, 0x0a, 0x01, 0x0e, 0xb5, - 0x18, 0x82, 0xdf, 0x03, 0x21, 0xd9, 0x91, 0xfb, 0x46, 0xec, 0xb4, 0x42, 0x0a, 0x1c, 0xe9, 0xb8, - 0x6f, 0x28, 0x3e, 0x84, 0x6d, 0x16, 0x4a, 0x14, 0xc6, 0x96, 0xcd, 0x11, 0xf9, 0x6c, 0x8d, 0x5c, - 0xaf, 0xcd, 0x71, 0xd1, 0x1e, 0xce, 0x75, 0xc6, 0x0b, 0xdc, 0xac, 0xe4, 0x3a, 0xe3, 0x39, 0xee, - 0x1e, 0x14, 0xe9, 0x28, 0x88, 0x27, 0x36, 0x0f, 0x25, 0xbb, 0x08, 0x1c, 0x6a, 0x30, 0x24, 0x69, - 0x9f, 0xba, 0xb6, 0x7d, 0xc6, 0xa7, 0x00, 0x77, 0x43, 0x8e, 0x1f, 0x43, 0x8e, 0x7a, 0x71, 0xe8, - 0xd2, 0x88, 0xdf, 0x72, 0x61, 0x85, 0x4c, 0x2f, 0x0e, 0x27, 0x64, 0xca, 0x30, 0xbe, 0x97, 0xa6, - 0x1c, 0x7e, 0x4b, 0x2b, 0x7e, 0xb7, 0x78, 0x3f, 0x21, 0xd8, 0x59, 0xb5, 0xa8, 0xf8, 0x78, 0xf1, - 0x0e, 0x6b, 0xd6, 0x7a, 0xfe, 0x36, 0xb8, 0x0a, 0x9b, 0x43, 0xdf, 0x7f, 0x7d, 0x15, 0xd8, 0x7c, - 0x80, 0x22, 0x3d, 0xbd, 0xf2, 0x13, 0xbb, 0x21, 0x48, 0x5c, 0x8c, 0x8c, 0x5f, 0x96, 0x93, 0x10, - 0xd5, 0xf8, 0x64, 0xbe, 0x1a, 0x7b, 0x4b, 0x29, 0xac, 0xab, 0xcb, 0xe7, 0x4b, 0x75, 0x31, 0x96, - 0x6c, 0x1f, 0x58, 0xa1, 0x09, 0xe8, 0xeb, 0xe2, 0xfd, 0x9f, 0x4f, 0x12, 0x9e, 0x79, 0x92, 0x14, - 0xf9, 0x04, 0xfd, 0x8a, 0x60, 0xf7, 0x3f, 0xf2, 0x5d, 0x11, 0xbe, 0x3a, 0xf7, 0x1a, 0xdd, 0x57, - 0x2f, 0xf9, 0x2e, 0x1d, 0xcf, 0xbf, 0x4b, 0xf7, 0x5a, 0x09, 0xf6, 0x21, 0x05, 0x55, 0xec, 0x00, - 0x2e, 0x42, 0xee, 0xa2, 0x65, 0x37, 0x4f, 0x3a, 0x4d, 0x2d, 0x85, 0x01, 0xd4, 0x4e, 0xf3, 0xa4, - 0x72, 0x5c, 0xd3, 0x90, 0x3c, 0x1f, 0x3f, 0xa9, 0x68, 0x69, 0x76, 0x3e, 0x33, 0x1b, 0x8d, 0x93, - 0x33, 0x2d, 0x83, 0x37, 0xa1, 0x40, 0xac, 0xb6, 0xf9, 0xe5, 0xe9, 0x93, 0xda, 0xc7, 0x5a, 0x96, - 0xd9, 0xd7, 0xad, 0x6e, 0xa3, 0x65, 0x5d, 0x68, 0x0a, 0x2e, 0x01, 0x08, 0x1b, 0x9b, 0xf9, 0x50, - 0x0f, 0x7f, 0x47, 0x90, 0x9f, 0x7e, 0x74, 0x99, 0xe1, 0x45, 0xcb, 0x6e, 0x13, 0xf3, 0x99, 0xf5, - 0x42, 0x4b, 0x31, 0xf1, 0xf9, 0x09, 0xb1, 0xdb, 0xa4, 0xd5, 0x6d, 0x69, 0x88, 0xf9, 0x61, 0x22, - 0x39, 0x6f, 0x6b, 0x69, 0xbc, 0x05, 0xc5, 0x67, 0xd6, 0x0b, 0xf3, 0xb4, 0x5a, 0xb1, 0xeb, 0xd6, - 0x17, 0x5a, 0x06, 0x63, 0x28, 0x4d, 0x81, 0x73, 0xab, 0xdb, 0x3d, 0x37, 0xb5, 0x6c, 0x42, 0xaa, - 0x3d, 0xe5, 0x24, 0x25, 0x21, 0xd5, 0x9e, 0x4e, 0x49, 0x2a, 0xde, 0x01, 0x8d, 0x98, 0x5f, 0x7d, - 0x6d, 0x11, 0xd3, 0x66, 0xce, 0xbe, 0xe9, 0x9a, 0x1d, 0x2d, 0x37, 0x8b, 0x32, 0x6b, 0x8e, 0xe6, - 0xeb, 0xfa, 0x1f, 0x37, 0x65, 0x74, 0x7d, 0x53, 0x46, 0x7f, 0xdd, 0x94, 0xd1, 0xcf, 0xb7, 0xe5, - 0xd4, 0xf5, 0x6d, 0x39, 0xf5, 0xe7, 0x6d, 0x39, 0xf5, 0x52, 0xe5, 0xbf, 0x37, 0xd5, 0x7f, 0x03, - 0x00, 0x00, 0xff, 0xff, 0xd4, 0x7d, 0x87, 0x8f, 0xee, 0x08, 0x00, 0x00, + // 973 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x96, 0xdd, 0x6e, 0xe3, 0x44, + 0x14, 0xc7, 0xe3, 0x24, 0x76, 0x92, 0x93, 0x36, 0x75, 0x47, 0x05, 0x59, 0x54, 0x9b, 0x16, 0xdf, + 0xd0, 0xed, 0x8a, 0xc2, 0x26, 0xdb, 0x20, 0x2e, 0x90, 0x48, 0x52, 0x2f, 0xb1, 0x5a, 0x9a, 0x30, + 0x09, 0xab, 0x45, 0x42, 0xb2, 0xdc, 0x74, 0xb2, 0xb1, 0x36, 0xfe, 0x90, 0xed, 0xa2, 0x64, 0x05, + 0x42, 0xe2, 0x09, 0xb8, 0x86, 0x47, 0xe0, 0x45, 0xb8, 0xec, 0x25, 0x97, 0xa8, 0x15, 0xe2, 0x82, + 0x97, 0x40, 0xf3, 0x11, 0x37, 0x9f, 0xb4, 0x17, 0x68, 0xef, 0x3c, 0xff, 0xf3, 0x3b, 0x33, 0x67, + 0xce, 0x39, 0x33, 0x63, 0xd8, 0x08, 0x42, 0xdf, 0x1f, 0x44, 0x47, 0x41, 0xe8, 0xc7, 0x3e, 0x92, + 0x9d, 0x7e, 0x54, 0xa9, 0xea, 0x3f, 0x42, 0xc9, 0x18, 0x3b, 0x51, 0x4c, 0xbc, 0x3e, 0xe9, 0x50, + 0x3b, 0x52, 0x21, 0xf3, 0x9a, 0x4c, 0x34, 0x69, 0x5f, 0x3a, 0xd8, 0xc0, 0xf4, 0x13, 0xed, 0x80, + 0xfc, 0x9d, 0x3d, 0xba, 0x22, 0x5a, 0x9a, 0x69, 0x7c, 0x80, 0xde, 0x87, 0xec, 0x88, 0xd8, 0x03, + 0x2d, 0xb3, 0x2f, 0x1d, 0x14, 0x2b, 0x9b, 0x47, 0x6c, 0xbe, 0xa3, 0x33, 0x62, 0x0f, 0xda, 0x01, + 0x66, 0x26, 0xa4, 0x43, 0x36, 0xb0, 0xe3, 0xa1, 0x96, 0xdd, 0xcf, 0x1c, 0x14, 0x2b, 0x25, 0x81, + 0x98, 0x9e, 0x47, 0x42, 0xca, 0x50, 0x9b, 0xfe, 0x03, 0x6c, 0x9f, 0xfb, 0xde, 0xbd, 0x31, 0x3c, + 0xa6, 0xab, 0x0d, 0x62, 0x16, 0x42, 0xb1, 0xf2, 0x8e, 0x98, 0x6a, 0xde, 0x0d, 0x33, 0x04, 0x3d, + 0x01, 0x39, 0x74, 0x5e, 0x0d, 0x63, 0x11, 0xd9, 0x1a, 0x96, 0x33, 0xfa, 0x3f, 0x12, 0x6c, 0x35, + 0x7d, 0xd7, 0x75, 0x62, 0x97, 0x78, 0x31, 0x5f, 0xfd, 0x43, 0x90, 0x09, 0x85, 0xd9, 0xfa, 0xeb, + 0x26, 0x68, 0xa5, 0x30, 0xa7, 0x50, 0x0d, 0xf2, 0x9e, 0xef, 0x71, 0x0f, 0x1e, 0x9e, 0x26, 0x3c, + 0x96, 0x36, 0xd6, 0x4a, 0xe1, 0x84, 0x45, 0x8f, 0x41, 0xbe, 0xb0, 0xe3, 0xfe, 0x50, 0xc4, 0xb9, + 0x2d, 0x9c, 0x1a, 0x54, 0x4b, 0x96, 0x60, 0x04, 0xfa, 0x0c, 0xa0, 0xef, 0xbb, 0x41, 0x48, 0xa2, + 0x88, 0x5c, 0x6a, 0x59, 0xc6, 0xef, 0x0a, 0xbe, 0x99, 0x18, 0xe6, 0x3c, 0x67, 0x1c, 0x1a, 0x39, + 0x90, 0x59, 0xed, 0xf5, 0x6b, 0x09, 0x14, 0x5e, 0x21, 0x5a, 0xbe, 0xa1, 0x1d, 0x0d, 0xd9, 0x1e, + 0x4b, 0x49, 0xf9, 0x5a, 0x76, 0x34, 0xa4, 0xa5, 0xa1, 0x26, 0x74, 0x04, 0xc5, 0x20, 0x24, 0xf4, + 0xd3, 0xa2, 0xd5, 0x48, 0xaf, 0x22, 0x41, 0x10, 0xa7, 0x64, 0x82, 0x2a, 0xb0, 0x39, 0xe5, 0x79, + 0xbf, 0x64, 0x56, 0x79, 0x6c, 0x08, 0xe6, 0x05, 0xeb, 0xa2, 0x0f, 0x40, 0x19, 0x11, 0xef, 0x15, + 0x6b, 0x12, 0x0a, 0x6f, 0x25, 0x7d, 0x44, 0xc5, 0x76, 0x80, 0x85, 0x19, 0xbd, 0x0b, 0x4a, 0x10, + 0x92, 0x81, 0x33, 0xd6, 0x64, 0xd6, 0x15, 0x62, 0xa4, 0x7f, 0x0b, 0x39, 0xd1, 0x50, 0x0f, 0xd9, + 0xd2, 0xdd, 0x2c, 0xe9, 0xd9, 0x59, 0xa8, 0x1e, 0x5d, 0x0d, 0xa8, 0x9e, 0xe1, 0x3a, 0x1f, 0xe9, + 0x7f, 0x49, 0x50, 0x60, 0x19, 0xed, 0x06, 0xa4, 0x8f, 0x0e, 0xa1, 0x40, 0xfb, 0xda, 0x8a, 0x02, + 0xd2, 0x17, 0xcd, 0xb1, 0xd0, 0xf7, 0x79, 0x6a, 0x67, 0xec, 0x47, 0x00, 0x0e, 0x8d, 0x8b, 0xc3, + 0xbc, 0x2f, 0xd4, 0xd9, 0x13, 0x40, 0x29, 0x5c, 0x70, 0xa6, 0x9f, 0x68, 0x17, 0x0a, 0xae, 0x3d, + 0xb6, 0x2e, 0x49, 0x10, 0xf3, 0x96, 0x90, 0x71, 0xde, 0xb5, 0xc7, 0x27, 0x74, 0xcc, 0x8c, 0x8e, + 0x27, 0x8c, 0x59, 0x61, 0x74, 0x3c, 0x6e, 0xac, 0xc3, 0xa3, 0x99, 0x3a, 0x59, 0x17, 0x64, 0xe0, + 0x87, 0xc4, 0xa2, 0xf5, 0xb7, 0x43, 0x27, 0xf2, 0x3d, 0x96, 0xb1, 0x3c, 0x7e, 0xef, 0xae, 0x54, + 0x0d, 0x86, 0x34, 0x13, 0x42, 0xff, 0x5b, 0x82, 0x42, 0x12, 0x15, 0xda, 0x83, 0x62, 0x7f, 0xe8, + 0x8c, 0x2e, 0x2d, 0x3f, 0xbc, 0x24, 0xa1, 0x26, 0xed, 0x67, 0x0e, 0x64, 0x0c, 0x4c, 0x6a, 0x53, + 0x05, 0x3d, 0x02, 0x3e, 0xb2, 0x22, 0xe7, 0x0d, 0xbf, 0x16, 0x64, 0x5c, 0x60, 0x4a, 0xd7, 0x79, + 0x43, 0xd0, 0x21, 0x6c, 0xd3, 0x68, 0x79, 0x6e, 0x2d, 0x51, 0x5f, 0xbe, 0xa5, 0x2d, 0xd7, 0xf1, + 0x3a, 0x4c, 0xe7, 0x15, 0x66, 0xac, 0x3d, 0x5e, 0x60, 0xb3, 0x82, 0xb5, 0xc7, 0x73, 0xec, 0x1e, + 0x14, 0x89, 0x1b, 0xc4, 0x13, 0x8b, 0x2d, 0x25, 0x1a, 0x01, 0x98, 0xd4, 0xa4, 0x4a, 0xd2, 0x01, + 0xca, 0xda, 0x0e, 0xd0, 0x3f, 0x05, 0xb8, 0x3b, 0x27, 0xe8, 0x09, 0xe4, 0x88, 0x17, 0x87, 0x0e, + 0x89, 0xd8, 0x2e, 0x17, 0x4e, 0xa1, 0xe1, 0xc5, 0xe1, 0x04, 0x4f, 0x09, 0xfd, 0x7b, 0xe1, 0xca, + 0xe4, 0xb7, 0x74, 0x4b, 0xdc, 0x9d, 0xdd, 0x9f, 0x24, 0xd8, 0x59, 0x75, 0xd6, 0xd1, 0xf1, 0xe2, + 0x1e, 0xd6, 0xdc, 0x0c, 0xf3, 0xbb, 0x41, 0x55, 0xd8, 0x1c, 0xf9, 0xfe, 0xeb, 0xab, 0xc0, 0x62, + 0x3d, 0x18, 0x69, 0xe9, 0x95, 0xb7, 0xf4, 0x06, 0x87, 0xd8, 0x30, 0xd2, 0x7f, 0x59, 0x0e, 0x82, + 0x67, 0xe3, 0x93, 0xf9, 0x6c, 0xec, 0x2d, 0x85, 0xb0, 0x2e, 0x2f, 0x9f, 0x2f, 0xe5, 0x45, 0x5f, + 0xf2, 0x7d, 0x60, 0x86, 0x26, 0xa0, 0xad, 0x5b, 0xef, 0xff, 0x7c, 0xd5, 0xd0, 0xcc, 0xab, 0x26, + 0x8b, 0x57, 0xec, 0x57, 0x09, 0x76, 0xff, 0x23, 0xde, 0x15, 0xcb, 0x57, 0xe7, 0x1e, 0xb4, 0xfb, + 0xf2, 0x25, 0x9e, 0xb6, 0xe3, 0xf9, 0xa7, 0xed, 0x5e, 0x2f, 0x4e, 0x1f, 0x12, 0x50, 0xf8, 0x19, + 0x40, 0x45, 0xc8, 0x9d, 0xb7, 0xad, 0x56, 0xbd, 0xdb, 0x52, 0x53, 0x08, 0x40, 0xe9, 0xb6, 0xea, + 0x95, 0xe3, 0x9a, 0x2a, 0x89, 0xef, 0xe3, 0xa7, 0x15, 0x35, 0x4d, 0xbf, 0x4f, 0x8d, 0x66, 0xb3, + 0x7e, 0xaa, 0x66, 0xd0, 0x26, 0x14, 0xb0, 0xd9, 0x31, 0xbe, 0x3c, 0x79, 0x5a, 0xfb, 0x58, 0xcd, + 0x52, 0xff, 0x86, 0xd9, 0x6b, 0xb6, 0xcd, 0x73, 0x55, 0x46, 0x25, 0x00, 0xee, 0x63, 0xd1, 0x39, + 0x94, 0xc3, 0xdf, 0x24, 0xc8, 0x4f, 0xef, 0x6d, 0xea, 0x78, 0xde, 0xb6, 0x3a, 0xd8, 0x78, 0x6e, + 0xbe, 0x54, 0x53, 0x74, 0xf8, 0xa2, 0x8e, 0xad, 0x0e, 0x6e, 0xf7, 0xda, 0xaa, 0x44, 0xe7, 0xa1, + 0x43, 0x7c, 0xd6, 0x51, 0xd3, 0x68, 0x0b, 0x8a, 0xcf, 0xcd, 0x97, 0xc6, 0x49, 0xb5, 0x62, 0x35, + 0xcc, 0x2f, 0xd4, 0x0c, 0x42, 0x50, 0x9a, 0x0a, 0x67, 0x66, 0xaf, 0x77, 0x66, 0xa8, 0xd9, 0x04, + 0xaa, 0x3d, 0x63, 0x90, 0x9c, 0x40, 0xb5, 0x67, 0x53, 0x48, 0x41, 0x3b, 0xa0, 0x62, 0xe3, 0xab, + 0xaf, 0x4d, 0x6c, 0x58, 0x74, 0xb2, 0x6f, 0x7a, 0x46, 0x57, 0xcd, 0xcd, 0xaa, 0xd4, 0x9b, 0xa9, + 0xf9, 0x86, 0xf6, 0xfb, 0x4d, 0x59, 0xba, 0xbe, 0x29, 0x4b, 0x7f, 0xde, 0x94, 0xa5, 0x9f, 0x6f, + 0xcb, 0xa9, 0xeb, 0xdb, 0x72, 0xea, 0x8f, 0xdb, 0x72, 0xea, 0x42, 0x61, 0x7f, 0x48, 0xd5, 0x7f, + 0x03, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x31, 0x09, 0xc2, 0x31, 0x09, 0x00, 0x00, } func (m *ExistenceProof) Marshal() (dAtA []byte, err error) { @@ -1565,6 +1577,16 @@ func (m *ProofSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.PrehashKeyBeforeComparison { + i-- + if m.PrehashKeyBeforeComparison { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } if m.MinDepth != 0 { i = encodeVarintProofs(dAtA, i, uint64(m.MinDepth)) i-- @@ -2213,6 +2235,9 @@ func (m *ProofSpec) Size() (n int) { if m.MinDepth != 0 { n += 1 + sovProofs(uint64(m.MinDepth)) } + if m.PrehashKeyBeforeComparison { + n += 2 + } return n } @@ -3381,6 +3406,26 @@ func (m *ProofSpec) Unmarshal(dAtA []byte) error { break } } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PrehashKeyBeforeComparison", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProofs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.PrehashKeyBeforeComparison = bool(v != 0) default: iNdEx = preIndex skippy, err := skipProofs(dAtA[iNdEx:]) diff --git a/js/src/generated/codecimpl.d.ts b/js/src/generated/codecimpl.d.ts index b49b82ff..1c311c76 100644 --- a/js/src/generated/codecimpl.d.ts +++ b/js/src/generated/codecimpl.d.ts @@ -703,6 +703,9 @@ export namespace ics23 { /** ProofSpec minDepth */ minDepth?: number | null; + + /** ProofSpec prehashKeyBeforeComparison */ + prehashKeyBeforeComparison?: boolean | null; } /** @@ -736,6 +739,9 @@ export namespace ics23 { /** ProofSpec minDepth. */ public minDepth: number; + /** ProofSpec prehashKeyBeforeComparison. */ + public prehashKeyBeforeComparison: boolean; + /** * Creates a new ProofSpec instance using the specified properties. * @param [properties] Properties to set diff --git a/js/src/generated/codecimpl.js b/js/src/generated/codecimpl.js index 5d87204a..dbf1a844 100644 --- a/js/src/generated/codecimpl.js +++ b/js/src/generated/codecimpl.js @@ -21,7 +21,7 @@ $root.ics23 = (function() { /** * HashOp enum. * @name ics23.HashOp - * @enum {string} + * @enum {number} * @property {number} NO_HASH=0 NO_HASH value * @property {number} SHA256=1 SHA256 value * @property {number} SHA512=2 SHA512 value @@ -48,7 +48,7 @@ $root.ics23 = (function() { * algorithm, the length will be prepended to the key and value bytes. * (Each one with it's own encoded length) * @name ics23.LengthOp - * @enum {string} + * @enum {number} * @property {number} NO_PREFIX=0 NO_PREFIX value * @property {number} VAR_PROTO=1 VAR_PROTO value * @property {number} VAR_RLP=2 VAR_RLP value @@ -175,11 +175,11 @@ $root.ics23 = (function() { ExistenceProof.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.key != null && message.hasOwnProperty("key")) + if (message.key != null && Object.hasOwnProperty.call(message, "key")) writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.key); - if (message.value != null && message.hasOwnProperty("value")) + if (message.value != null && Object.hasOwnProperty.call(message, "value")) writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value); - if (message.leaf != null && message.hasOwnProperty("leaf")) + if (message.leaf != null && Object.hasOwnProperty.call(message, "leaf")) $root.ics23.LeafOp.encode(message.leaf, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); if (message.path != null && message.path.length) for (var i = 0; i < message.path.length; ++i) @@ -464,11 +464,11 @@ $root.ics23 = (function() { NonExistenceProof.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.key != null && message.hasOwnProperty("key")) + if (message.key != null && Object.hasOwnProperty.call(message, "key")) writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.key); - if (message.left != null && message.hasOwnProperty("left")) + if (message.left != null && Object.hasOwnProperty.call(message, "left")) $root.ics23.ExistenceProof.encode(message.left, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.right != null && message.hasOwnProperty("right")) + if (message.right != null && Object.hasOwnProperty.call(message, "right")) $root.ics23.ExistenceProof.encode(message.right, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); return writer; }; @@ -738,13 +738,13 @@ $root.ics23 = (function() { CommitmentProof.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.exist != null && message.hasOwnProperty("exist")) + if (message.exist != null && Object.hasOwnProperty.call(message, "exist")) $root.ics23.ExistenceProof.encode(message.exist, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.nonexist != null && message.hasOwnProperty("nonexist")) + if (message.nonexist != null && Object.hasOwnProperty.call(message, "nonexist")) $root.ics23.NonExistenceProof.encode(message.nonexist, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.batch != null && message.hasOwnProperty("batch")) + if (message.batch != null && Object.hasOwnProperty.call(message, "batch")) $root.ics23.BatchProof.encode(message.batch, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.compressed != null && message.hasOwnProperty("compressed")) + if (message.compressed != null && Object.hasOwnProperty.call(message, "compressed")) $root.ics23.CompressedBatchProof.encode(message.compressed, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); return writer; }; @@ -1059,15 +1059,15 @@ $root.ics23 = (function() { LeafOp.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.hash != null && message.hasOwnProperty("hash")) + if (message.hash != null && Object.hasOwnProperty.call(message, "hash")) writer.uint32(/* id 1, wireType 0 =*/8).int32(message.hash); - if (message.prehashKey != null && message.hasOwnProperty("prehashKey")) + if (message.prehashKey != null && Object.hasOwnProperty.call(message, "prehashKey")) writer.uint32(/* id 2, wireType 0 =*/16).int32(message.prehashKey); - if (message.prehashValue != null && message.hasOwnProperty("prehashValue")) + if (message.prehashValue != null && Object.hasOwnProperty.call(message, "prehashValue")) writer.uint32(/* id 3, wireType 0 =*/24).int32(message.prehashValue); - if (message.length != null && message.hasOwnProperty("length")) + if (message.length != null && Object.hasOwnProperty.call(message, "length")) writer.uint32(/* id 4, wireType 0 =*/32).int32(message.length); - if (message.prefix != null && message.hasOwnProperty("prefix")) + if (message.prefix != null && Object.hasOwnProperty.call(message, "prefix")) writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.prefix); return writer; }; @@ -1502,11 +1502,11 @@ $root.ics23 = (function() { InnerOp.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.hash != null && message.hasOwnProperty("hash")) + if (message.hash != null && Object.hasOwnProperty.call(message, "hash")) writer.uint32(/* id 1, wireType 0 =*/8).int32(message.hash); - if (message.prefix != null && message.hasOwnProperty("prefix")) + if (message.prefix != null && Object.hasOwnProperty.call(message, "prefix")) writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.prefix); - if (message.suffix != null && message.hasOwnProperty("suffix")) + if (message.suffix != null && Object.hasOwnProperty.call(message, "suffix")) writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.suffix); return writer; }; @@ -1726,6 +1726,7 @@ $root.ics23 = (function() { * @property {ics23.IInnerSpec|null} [innerSpec] ProofSpec innerSpec * @property {number|null} [maxDepth] ProofSpec maxDepth * @property {number|null} [minDepth] ProofSpec minDepth + * @property {boolean|null} [prehashKeyBeforeComparison] ProofSpec prehashKeyBeforeComparison */ /** @@ -1784,6 +1785,14 @@ $root.ics23 = (function() { */ ProofSpec.prototype.minDepth = 0; + /** + * ProofSpec prehashKeyBeforeComparison. + * @member {boolean} prehashKeyBeforeComparison + * @memberof ics23.ProofSpec + * @instance + */ + ProofSpec.prototype.prehashKeyBeforeComparison = false; + /** * Creates a new ProofSpec instance using the specified properties. * @function create @@ -1808,14 +1817,16 @@ $root.ics23 = (function() { ProofSpec.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.leafSpec != null && message.hasOwnProperty("leafSpec")) + if (message.leafSpec != null && Object.hasOwnProperty.call(message, "leafSpec")) $root.ics23.LeafOp.encode(message.leafSpec, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.innerSpec != null && message.hasOwnProperty("innerSpec")) + if (message.innerSpec != null && Object.hasOwnProperty.call(message, "innerSpec")) $root.ics23.InnerSpec.encode(message.innerSpec, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.maxDepth != null && message.hasOwnProperty("maxDepth")) + if (message.maxDepth != null && Object.hasOwnProperty.call(message, "maxDepth")) writer.uint32(/* id 3, wireType 0 =*/24).int32(message.maxDepth); - if (message.minDepth != null && message.hasOwnProperty("minDepth")) + if (message.minDepth != null && Object.hasOwnProperty.call(message, "minDepth")) writer.uint32(/* id 4, wireType 0 =*/32).int32(message.minDepth); + if (message.prehashKeyBeforeComparison != null && Object.hasOwnProperty.call(message, "prehashKeyBeforeComparison")) + writer.uint32(/* id 5, wireType 0 =*/40).bool(message.prehashKeyBeforeComparison); return writer; }; @@ -1862,6 +1873,9 @@ $root.ics23 = (function() { case 4: message.minDepth = reader.int32(); break; + case 5: + message.prehashKeyBeforeComparison = reader.bool(); + break; default: reader.skipType(tag & 7); break; @@ -1913,6 +1927,9 @@ $root.ics23 = (function() { if (message.minDepth != null && message.hasOwnProperty("minDepth")) if (!$util.isInteger(message.minDepth)) return "minDepth: integer expected"; + if (message.prehashKeyBeforeComparison != null && message.hasOwnProperty("prehashKeyBeforeComparison")) + if (typeof message.prehashKeyBeforeComparison !== "boolean") + return "prehashKeyBeforeComparison: boolean expected"; return null; }; @@ -1942,6 +1959,8 @@ $root.ics23 = (function() { message.maxDepth = object.maxDepth | 0; if (object.minDepth != null) message.minDepth = object.minDepth | 0; + if (object.prehashKeyBeforeComparison != null) + message.prehashKeyBeforeComparison = Boolean(object.prehashKeyBeforeComparison); return message; }; @@ -1963,6 +1982,7 @@ $root.ics23 = (function() { object.innerSpec = null; object.maxDepth = 0; object.minDepth = 0; + object.prehashKeyBeforeComparison = false; } if (message.leafSpec != null && message.hasOwnProperty("leafSpec")) object.leafSpec = $root.ics23.LeafOp.toObject(message.leafSpec, options); @@ -1972,6 +1992,8 @@ $root.ics23 = (function() { object.maxDepth = message.maxDepth; if (message.minDepth != null && message.hasOwnProperty("minDepth")) object.minDepth = message.minDepth; + if (message.prehashKeyBeforeComparison != null && message.hasOwnProperty("prehashKeyBeforeComparison")) + object.prehashKeyBeforeComparison = message.prehashKeyBeforeComparison; return object; }; @@ -2097,15 +2119,15 @@ $root.ics23 = (function() { writer.int32(message.childOrder[i]); writer.ldelim(); } - if (message.childSize != null && message.hasOwnProperty("childSize")) + if (message.childSize != null && Object.hasOwnProperty.call(message, "childSize")) writer.uint32(/* id 2, wireType 0 =*/16).int32(message.childSize); - if (message.minPrefixLength != null && message.hasOwnProperty("minPrefixLength")) + if (message.minPrefixLength != null && Object.hasOwnProperty.call(message, "minPrefixLength")) writer.uint32(/* id 3, wireType 0 =*/24).int32(message.minPrefixLength); - if (message.maxPrefixLength != null && message.hasOwnProperty("maxPrefixLength")) + if (message.maxPrefixLength != null && Object.hasOwnProperty.call(message, "maxPrefixLength")) writer.uint32(/* id 4, wireType 0 =*/32).int32(message.maxPrefixLength); - if (message.emptyChild != null && message.hasOwnProperty("emptyChild")) + if (message.emptyChild != null && Object.hasOwnProperty.call(message, "emptyChild")) writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.emptyChild); - if (message.hash != null && message.hasOwnProperty("hash")) + if (message.hash != null && Object.hasOwnProperty.call(message, "hash")) writer.uint32(/* id 6, wireType 0 =*/48).int32(message.hash); return writer; }; @@ -2646,9 +2668,9 @@ $root.ics23 = (function() { BatchEntry.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.exist != null && message.hasOwnProperty("exist")) + if (message.exist != null && Object.hasOwnProperty.call(message, "exist")) $root.ics23.ExistenceProof.encode(message.exist, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.nonexist != null && message.hasOwnProperty("nonexist")) + if (message.nonexist != null && Object.hasOwnProperty.call(message, "nonexist")) $root.ics23.NonExistenceProof.encode(message.nonexist, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; @@ -3143,9 +3165,9 @@ $root.ics23 = (function() { CompressedBatchEntry.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.exist != null && message.hasOwnProperty("exist")) + if (message.exist != null && Object.hasOwnProperty.call(message, "exist")) $root.ics23.CompressedExistenceProof.encode(message.exist, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.nonexist != null && message.hasOwnProperty("nonexist")) + if (message.nonexist != null && Object.hasOwnProperty.call(message, "nonexist")) $root.ics23.CompressedNonExistenceProof.encode(message.nonexist, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; @@ -3393,11 +3415,11 @@ $root.ics23 = (function() { CompressedExistenceProof.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.key != null && message.hasOwnProperty("key")) + if (message.key != null && Object.hasOwnProperty.call(message, "key")) writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.key); - if (message.value != null && message.hasOwnProperty("value")) + if (message.value != null && Object.hasOwnProperty.call(message, "value")) writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value); - if (message.leaf != null && message.hasOwnProperty("leaf")) + if (message.leaf != null && Object.hasOwnProperty.call(message, "leaf")) $root.ics23.LeafOp.encode(message.leaf, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); if (message.path != null && message.path.length) { writer.uint32(/* id 4, wireType 2 =*/34).fork(); @@ -3685,11 +3707,11 @@ $root.ics23 = (function() { CompressedNonExistenceProof.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.key != null && message.hasOwnProperty("key")) + if (message.key != null && Object.hasOwnProperty.call(message, "key")) writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.key); - if (message.left != null && message.hasOwnProperty("left")) + if (message.left != null && Object.hasOwnProperty.call(message, "left")) $root.ics23.CompressedExistenceProof.encode(message.left, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.right != null && message.hasOwnProperty("right")) + if (message.right != null && Object.hasOwnProperty.call(message, "right")) $root.ics23.CompressedExistenceProof.encode(message.right, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); return writer; }; diff --git a/js/src/ics23.ts b/js/src/ics23.ts index c09c6ae8..510de566 100644 --- a/js/src/ics23.ts +++ b/js/src/ics23.ts @@ -1,8 +1,8 @@ import { decompress } from "./compress"; import { ics23 } from "./generated/codecimpl"; import { CommitmentRoot, verifyExistence, verifyNonExistence } from "./proofs"; +import { keyForComparison } from "./proofs"; import { bytesBefore, bytesEqual } from "./specs"; - /* This implements the client side functions as specified in https://github.com/cosmos/ics/tree/master/spec/ics-023-vector-commitments @@ -59,7 +59,7 @@ export function verifyNonMembership( key: Uint8Array ): boolean { const norm = decompress(proof); - const nonexist = getNonExistForKey(norm, key); + const nonexist = getNonExistForKey(spec, norm, key); if (!nonexist) { return false; } @@ -122,14 +122,23 @@ function getExistForKey( } function getNonExistForKey( + spec: ics23.IProofSpec, proof: ics23.ICommitmentProof, key: Uint8Array ): ics23.INonExistenceProof | undefined | null { const match = (p: ics23.INonExistenceProof | null | undefined): boolean => { return ( !!p && - (!p.left || bytesBefore(p.left.key!, key)) && - (!p.right || bytesBefore(key, p.right.key!)) + (!p.left || + bytesBefore( + keyForComparison(spec, p.left.key!), + keyForComparison(spec, key) + )) && + (!p.right || + bytesBefore( + keyForComparison(spec, key), + keyForComparison(spec, p.right.key!) + )) ); }; if (match(proof.nonexist)) { diff --git a/js/src/proofs.ts b/js/src/proofs.ts index 424b2306..40b44079 100644 --- a/js/src/proofs.ts +++ b/js/src/proofs.ts @@ -1,5 +1,6 @@ import { ics23 } from "./generated/codecimpl"; import { applyInner, applyLeaf } from "./ops"; +import { doHash } from "./ops"; import { bytesEqual, ensureBytesBefore, @@ -45,7 +46,7 @@ export const tendermintSpec: ics23.IProofSpec = { export const smtSpec: ics23.IProofSpec = { leafSpec: { hash: ics23.HashOp.SHA256, - prehashKey: ics23.HashOp.NO_HASH, + prehashKey: ics23.HashOp.SHA256, prehashValue: ics23.HashOp.SHA256, length: ics23.LengthOp.NO_PREFIX, prefix: Uint8Array.from([0]), @@ -59,10 +60,22 @@ export const smtSpec: ics23.IProofSpec = { hash: ics23.HashOp.SHA256, }, maxDepth: 256, + prehashKeyBeforeComparison: true, }; export type CommitmentRoot = Uint8Array; +export function keyForComparison( + spec: ics23.IProofSpec, + key: Uint8Array +): Uint8Array { + if (!spec.prehashKeyBeforeComparison) { + return key; + } + + return doHash(spec.leafSpec!.prehashKey!, key); +} + // verifyExistence will throw an error if the proof doesn't link key, value -> root // or if it doesn't fulfill the spec export function verifyExistence( @@ -111,10 +124,16 @@ export function verifyNonExistence( } if (leftKey) { - ensureBytesBefore(leftKey, key); + ensureBytesBefore( + keyForComparison(spec, leftKey), + keyForComparison(spec, key) + ); } if (rightKey) { - ensureBytesBefore(key, rightKey); + ensureBytesBefore( + keyForComparison(spec, key), + keyForComparison(spec, rightKey) + ); } if (!spec.innerSpec) { diff --git a/js/src/testvectors.spec.ts b/js/src/testvectors.spec.ts index 7cdbb758..cdc6620c 100644 --- a/js/src/testvectors.spec.ts +++ b/js/src/testvectors.spec.ts @@ -8,7 +8,7 @@ import { verifyMembership, verifyNonMembership, } from "./ics23"; -import { iavlSpec, tendermintSpec } from "./proofs"; +import { iavlSpec, smtSpec, tendermintSpec } from "./proofs"; import { fromHex } from "./testhelpers.spec"; describe("calculateExistenceRoot", () => { @@ -251,4 +251,28 @@ describe("calculateExistenceRoot", () => { ]); validateBatch(proof, tendermintSpec, data[3]); }); + + it("should validate smt batch exist", () => { + const { proof, data } = loadBatch([ + "../testdata/smt/exist_left.json", + "../testdata/smt/exist_right.json", + "../testdata/smt/exist_middle.json", + "../testdata/smt/nonexist_left.json", + "../testdata/smt/nonexist_right.json", + "../testdata/smt/nonexist_middle.json", + ]); + validateBatch(proof, smtSpec, data[2]); + }); + + it("should validate smt batch nonexist", () => { + const { proof, data } = loadBatch([ + "../testdata/smt/exist_left.json", + "../testdata/smt/exist_right.json", + "../testdata/smt/exist_middle.json", + "../testdata/smt/nonexist_left.json", + "../testdata/smt/nonexist_right.json", + "../testdata/smt/nonexist_middle.json", + ]); + validateBatch(proof, smtSpec, data[3]); + }); }); diff --git a/proofs.proto b/proofs.proto index 12d9e2da..e3fde718 100644 --- a/proofs.proto +++ b/proofs.proto @@ -162,6 +162,10 @@ message ProofSpec { int32 max_depth = 3; // min_depth (if > 0) is the minimum number of InnerOps allowed (mainly for fixed-depth tries) int32 min_depth = 4; + // prehash_key_before_comparison is a flag that indicates whether to use the + // prehash_key specified by LeafOp to compare lexical ordering of keys for + // non-existence proofs. + bool prehash_key_before_comparison = 5; } /* diff --git a/rust/codegen/src/main.rs b/rust/codegen/src/main.rs index 1cec7bbe..d8a4a06e 100644 --- a/rust/codegen/src/main.rs +++ b/rust/codegen/src/main.rs @@ -13,7 +13,9 @@ fn main() { let out_dir: &str = &format!("{}{}", root, "/rust/src"); let input: &str = &format!("{}{}", root, "/proofs.proto"); - let mut cfg = prost_build::Config::new(); - cfg.out_dir(&out_dir); - cfg.compile_protos(&[input], &[root]).unwrap(); + prost_build::Config::new() + .out_dir(&out_dir) + .format(true) + .compile_protos(&[input], &[root]) + .unwrap(); } diff --git a/rust/src/api.rs b/rust/src/api.rs index 4944422e..696aaa1c 100644 --- a/rust/src/api.rs +++ b/rust/src/api.rs @@ -4,6 +4,7 @@ use alloc::vec; use crate::compress::{decompress, is_compressed}; use crate::host_functions::HostFunctionsProvider; use crate::ics23; +use crate::ops::do_hash; use crate::verify::{verify_existence, verify_non_existence, CommitmentRoot}; // Use CommitmentRoot vs &[u8] to stick with ics naming @@ -56,7 +57,7 @@ pub fn verify_non_membership( } } - if let Some(non) = get_nonexist_proof(proof, key) { + if let Some(non) = get_nonexist_proof::(proof, key, spec) { let valid = verify_non_existence::(non, spec, root, key); valid.is_ok() } else { @@ -131,18 +132,53 @@ fn get_exist_proof<'a>( } } -fn get_nonexist_proof<'a>( +fn get_nonexist_proof<'a, H: HostFunctionsProvider>( proof: &'a ics23::CommitmentProof, key: &[u8], + spec: &ics23::ProofSpec, ) -> Option<&'a ics23::NonExistenceProof> { + // If we should prehash the key before comparison, do so; otherwise, return the key. Prehashing + // changes lexical comparison, so if the spec sets `prehash_key_before_comparison` to true, we + // should compare keys on their hashes by prehashing them before comparison. + let key_for_comparison = |key: &[u8]| match spec.prehash_key_before_comparison { + true => do_hash::( + spec.leaf_spec + .as_ref() + .map(|leaf_spec| leaf_spec.prehash_key()) + .unwrap_or_default(), + key, + ), + false => key.to_vec(), + }; + match &proof.proof { - Some(ics23::commitment_proof::Proof::Nonexist(non)) => Some(non), + Some(ics23::commitment_proof::Proof::Nonexist(non)) => { + // use iter/all - true if None, must check if Some + if non + .left + .iter() + .all(|x| key_for_comparison(&x.key) < key_for_comparison(key)) + && non + .right + .iter() + .all(|x| key_for_comparison(&x.key) > key_for_comparison(key)) + { + return Some(non); + } + None + } Some(ics23::commitment_proof::Proof::Batch(batch)) => { for entry in &batch.entries { if let Some(ics23::batch_entry::Proof::Nonexist(non)) = &entry.proof { // use iter/all - true if None, must check if Some - if non.left.iter().all(|x| x.key.as_slice() < key) - && non.right.iter().all(|x| x.key.as_slice() > key) + if non + .left + .iter() + .all(|x| key_for_comparison(&x.key) < key_for_comparison(key)) + && non + .right + .iter() + .all(|x| key_for_comparison(&x.key) > key_for_comparison(key)) { return Some(non); } @@ -176,6 +212,7 @@ pub fn iavl_spec() -> ics23::ProofSpec { inner_spec: Some(inner), min_depth: 0, max_depth: 0, + prehash_key_before_comparison: false, } } @@ -200,13 +237,14 @@ pub fn tendermint_spec() -> ics23::ProofSpec { inner_spec: Some(inner), min_depth: 0, max_depth: 0, + prehash_key_before_comparison: false, } } pub fn smt_spec() -> ics23::ProofSpec { let leaf = ics23::LeafOp { hash: ics23::HashOp::Sha256.into(), - prehash_key: 0, + prehash_key: ics23::HashOp::Sha256.into(), prehash_value: ics23::HashOp::Sha256.into(), length: 0, prefix: vec![0_u8], @@ -224,6 +262,7 @@ pub fn smt_spec() -> ics23::ProofSpec { inner_spec: Some(inner), min_depth: 0, max_depth: 0, + prehash_key_before_comparison: true, } } diff --git a/rust/src/ics23.rs b/rust/src/ics23.rs index 45b7b895..a383fe73 100644 --- a/rust/src/ics23.rs +++ b/rust/src/ics23.rs @@ -18,7 +18,8 @@ /// With LengthOp this is tricker but not impossible. Which is why the "leafPrefixEqual" field /// in the ProofSpec is valuable to prevent this mutability. And why all trees should /// length-prefix the data before hashing it. -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct ExistenceProof { #[prost(bytes = "vec", tag = "1")] pub key: ::prost::alloc::vec::Vec, @@ -33,7 +34,8 @@ pub struct ExistenceProof { /// NonExistenceProof takes a proof of two neighbors, one left of the desired key, /// one right of the desired key. If both proofs are valid AND they are neighbors, /// then there is no valid proof for the given key. -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct NonExistenceProof { /// TODO: remove this as unnecessary??? we prove a range #[prost(bytes = "vec", tag = "1")] @@ -45,14 +47,16 @@ pub struct NonExistenceProof { } /// /// CommitmentProof is either an ExistenceProof or a NonExistenceProof, or a Batch of such messages -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct CommitmentProof { #[prost(oneof = "commitment_proof::Proof", tags = "1, 2, 3, 4")] pub proof: ::core::option::Option, } /// Nested message and enum types in `CommitmentProof`. pub mod commitment_proof { - #[derive(Clone, PartialEq, Eq, ::prost::Oneof)] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Proof { #[prost(message, tag = "1")] Exist(super::ExistenceProof), @@ -79,7 +83,8 @@ pub mod commitment_proof { /// /// Then combine the bytes, and hash it /// output = hash(prefix || length(hkey) || hkey || length(hvalue) || hvalue) -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct LeafOp { #[prost(enumeration = "HashOp", tag = "1")] pub hash: i32, @@ -110,7 +115,8 @@ pub struct LeafOp { /// Any special data, like prepending child with the length, or prepending the entire operation with /// some value to differentiate from leaf nodes, should be included in prefix and suffix. /// If either of prefix or suffix is empty, we just treat it as an empty string -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct InnerOp { #[prost(enumeration = "HashOp", tag = "1")] pub hash: i32, @@ -130,7 +136,8 @@ pub struct InnerOp { /// generate a given hash (by interpretting the preimage differently). /// We need this for proper security, requires client knows a priori what /// tree format server uses. But not in code, rather a configuration object. -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct ProofSpec { /// any field in the ExistenceProof must be the same as in this spec. /// except Prefix, which is just the first bytes of prefix (spec can be longer) @@ -144,6 +151,11 @@ pub struct ProofSpec { /// min_depth (if > 0) is the minimum number of InnerOps allowed (mainly for fixed-depth tries) #[prost(int32, tag = "4")] pub min_depth: i32, + /// prehash_key_before_comparison is a flag that indicates whether to use the + /// prehash_key specified by LeafOp to compare lexical ordering of keys for + /// non-existence proofs. + #[prost(bool, tag = "5")] + pub prehash_key_before_comparison: bool, } /// /// InnerSpec contains all store-specific structure info to determine if two proofs from a @@ -154,7 +166,8 @@ pub struct ProofSpec { /// isLeftMost(spec: InnerSpec, op: InnerOp) /// isRightMost(spec: InnerSpec, op: InnerOp) /// isLeftNeighbor(spec: InnerSpec, left: InnerOp, right: InnerOp) -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct InnerSpec { /// Child order is the ordering of the children node, must count from 0 /// iavl tree is [0, 1] (left then right) @@ -176,20 +189,23 @@ pub struct InnerSpec { } /// /// BatchProof is a group of multiple proof types than can be compressed -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct BatchProof { #[prost(message, repeated, tag = "1")] pub entries: ::prost::alloc::vec::Vec, } /// Use BatchEntry not CommitmentProof, to avoid recursion -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct BatchEntry { #[prost(oneof = "batch_entry::Proof", tags = "1, 2")] pub proof: ::core::option::Option, } /// Nested message and enum types in `BatchEntry`. pub mod batch_entry { - #[derive(Clone, PartialEq, Eq, ::prost::Oneof)] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Proof { #[prost(message, tag = "1")] Exist(super::ExistenceProof), @@ -197,9 +213,8 @@ pub mod batch_entry { Nonexist(super::NonExistenceProof), } } -// ***** all items here are compressed forms ****** - -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct CompressedBatchProof { #[prost(message, repeated, tag = "1")] pub entries: ::prost::alloc::vec::Vec, @@ -207,14 +222,16 @@ pub struct CompressedBatchProof { pub lookup_inners: ::prost::alloc::vec::Vec, } /// Use BatchEntry not CommitmentProof, to avoid recursion -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct CompressedBatchEntry { #[prost(oneof = "compressed_batch_entry::Proof", tags = "1, 2")] pub proof: ::core::option::Option, } /// Nested message and enum types in `CompressedBatchEntry`. pub mod compressed_batch_entry { - #[derive(Clone, PartialEq, Eq, ::prost::Oneof)] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Proof { #[prost(message, tag = "1")] Exist(super::CompressedExistenceProof), @@ -222,7 +239,8 @@ pub mod compressed_batch_entry { Nonexist(super::CompressedNonExistenceProof), } } -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct CompressedExistenceProof { #[prost(bytes = "vec", tag = "1")] pub key: ::prost::alloc::vec::Vec, @@ -234,7 +252,8 @@ pub struct CompressedExistenceProof { #[prost(int32, repeated, tag = "4")] pub path: ::prost::alloc::vec::Vec, } -#[derive(Clone, PartialEq, Eq, ::prost::Message)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct CompressedNonExistenceProof { /// TODO: remove this as unnecessary??? we prove a range #[prost(bytes = "vec", tag = "1")] @@ -273,6 +292,19 @@ impl HashOp { HashOp::Sha512256 => "SHA512_256", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "NO_HASH" => Some(Self::NoHash), + "SHA256" => Some(Self::Sha256), + "SHA512" => Some(Self::Sha512), + "KECCAK" => Some(Self::Keccak), + "RIPEMD160" => Some(Self::Ripemd160), + "BITCOIN" => Some(Self::Bitcoin), + "SHA512_256" => Some(Self::Sha512256), + _ => None, + } + } } /// * /// LengthOp defines how to process the key and value of the LeafOp @@ -319,4 +351,19 @@ impl LengthOp { LengthOp::Require64Bytes => "REQUIRE_64_BYTES", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "NO_PREFIX" => Some(Self::NoPrefix), + "VAR_PROTO" => Some(Self::VarProto), + "VAR_RLP" => Some(Self::VarRlp), + "FIXED32_BIG" => Some(Self::Fixed32Big), + "FIXED32_LITTLE" => Some(Self::Fixed32Little), + "FIXED64_BIG" => Some(Self::Fixed64Big), + "FIXED64_LITTLE" => Some(Self::Fixed64Little), + "REQUIRE_32_BYTES" => Some(Self::Require32Bytes), + "REQUIRE_64_BYTES" => Some(Self::Require64Bytes), + _ => None, + } + } } diff --git a/rust/src/ops.rs b/rust/src/ops.rs index 094beaf7..d8d3141a 100644 --- a/rust/src/ops.rs +++ b/rust/src/ops.rs @@ -37,7 +37,7 @@ fn prepare_leaf_data( do_length(length, &h) } -fn do_hash(hash: HashOp, data: &[u8]) -> Hash { +pub(crate) fn do_hash(hash: HashOp, data: &[u8]) -> Hash { match hash { HashOp::NoHash => Hash::from(data), HashOp::Sha256 => Hash::from(H::sha2_256(data)), diff --git a/rust/src/verify.rs b/rust/src/verify.rs index 2dc84420..9ce8ef87 100644 --- a/rust/src/verify.rs +++ b/rust/src/verify.rs @@ -6,6 +6,7 @@ use anyhow::{bail, ensure}; use crate::helpers::Result; use crate::host_functions::HostFunctionsProvider; use crate::ics23; +use crate::ops::do_hash; use crate::ops::{apply_inner, apply_leaf}; use alloc::vec::Vec; @@ -33,13 +34,29 @@ pub fn verify_non_existence( root: &[u8], key: &[u8], ) -> Result<()> { + let key_for_comparison = |key: &[u8]| -> Vec { + match spec.prehash_key_before_comparison { + true => do_hash::( + spec.leaf_spec.clone().unwrap_or_default().prehash_key(), + key, + ), + false => key.to_vec(), + } + }; + if let Some(left) = &proof.left { verify_existence::(left, spec, root, &left.key, &left.value)?; - ensure!(key > left.key.as_slice(), "left key isn't before key"); + ensure!( + key_for_comparison(key) > key_for_comparison(&left.key), + "left key isn't before key" + ); } if let Some(right) = &proof.right { verify_existence::(right, spec, root, &right.key, &right.value)?; - ensure!(key < right.key.as_slice(), "right key isn't after key"); + ensure!( + key_for_comparison(key) < key_for_comparison(&right.key), + "right key isn't after key" + ); } if let Some(inner) = &spec.inner_spec { @@ -606,6 +623,7 @@ mod tests { inner_spec: Some(inner), min_depth: 0, max_depth: 0, + prehash_key_before_comparison: false, } } diff --git a/testdata/smt/batch_exist.json b/testdata/smt/batch_exist.json index 6bd3b26f..0b43268f 100644 --- a/testdata/smt/batch_exist.json +++ b/testdata/smt/batch_exist.json @@ -1,86 +1,86 @@ { "items": [ { - "key": "002c041fe1df37d806cc5b493bed02222d83b25ffebf9cb529b4524cc547fbeb", + "key": "636c536e4d46714a4e6162776a7a5134356e6d4d", "value": "76616c75655f666f725f636c536e4d46714a4e6162776a7a5134356e6d4d" }, { - "key": "fffa9eb3a5e49b7261d86e27c0e1c17f39215887308f5e3ca48e3264b03d2a2f", + "key": "6b63395874466e5a4645784d416f4b6f37566c5a", "value": "76616c75655f666f725f6b63395874466e5a4645784d416f4b6f37566c5a" }, { - "key": "d905fdfb0063d1ae1cfb60037460005c24e77d0214d3f88f17e44ccfa302c533", + "key": "426f4c4f5279574251784c695835754c7257524a", "value": "76616c75655f666f725f426f4c4f5279574251784c695835754c7257524a" }, { - "key": "85e3ed5362f3659ec475645ad63d9f23a1ce81cfdcbd17318768ea8133871a7d", + "key": "483977566967584c6d3330756f726a4b53423371", "value": "76616c75655f666f725f483977566967584c6d3330756f726a4b53423371" }, { - "key": "3df3a2ba5c2e903ce8a4f8fe8dda64f5973de99cdea4361a4873a00e0783ee06", + "key": "687848476735394278645a725657575647366239", "value": "76616c75655f666f725f687848476735394278645a725657575647366239" }, { - "key": "a66a205c2b5a6101ceb0c39823500f9b10681e2c4ae2efa5f977a871faf77b1d", + "key": "6f62695655544657735949374a7a6c62654e3074", "value": "76616c75655f666f725f6f62695655544657735949374a7a6c62654e3074" }, { - "key": "16659734ab7c95e3043ae7896fea9191a6a4d79186ea87e11c0414c2511d7e7f", + "key": "683139594138737249614956386b557936315672", "value": "76616c75655f666f725f683139594138737249614956386b557936315672" }, { - "key": "b2943d32dde246b9140e0d97dbb1061ea681a385eca7abcc6d6b2b88ba4d5dbd", + "key": "6e586b6e744366514d53436a39625963516e325a", "value": "76616c75655f666f725f6e586b6e744366514d53436a39625963516e325a" }, { - "key": "50ce16abe59462be0c5e6c67c865a281b91cf99d0e30bb324c97d69d611d9b70", + "key": "7542684a444c57425a7338765569786e6b314449", "value": "76616c75655f666f725f7542684a444c57425a7338765569786e6b314449" }, { - "key": "35684a8bb5bab8674ec7e6f19efc5cac19a2d6df21b8156bf86f6e86ab19d2e1", + "key": "56336e7859534c6c4a6b3739646d776b3330634b", "value": "76616c75655f666f725f56336e7859534c6c4a6b3739646d776b3330634b" }, { - "key": "153b5591bd409f92b9ac8a997abaab4cd79b6c41f923b8541c3ba5a1dd26953f", + "key": "395277644d4b354e786d506942755950454e695a", "value": "76616c75655f666f725f395277644d4b354e786d506942755950454e695a" }, { - "key": "266c8f74eb0f2d19314153c5ec74aa343e79064bee1bd4280a5e3d2bb121dc27", + "key": "746b425246386e79314e4f35775244514d376c46", "value": "76616c75655f666f725f746b425246386e79314e4f35775244514d376c46" }, { - "key": "c7bcf000bd45ae83a6020d590a9d33cd29dfef1bdb2e98ba2482a489a48a8c13", + "key": "4e41334178576a42485233524b746a5071306575", "value": "76616c75655f666f725f4e41334178576a42485233524b746a5071306575" }, { - "key": "d6f4d73207bcd05b9306710c8bd012bd198dd0383255ae72b56aa70850dfa1d6", + "key": "5559656353686a697731476b3942494b66686f6d", "value": "76616c75655f666f725f5559656353686a697731476b3942494b66686f6d" }, { - "key": "a57e080d7762b2ba42323ac47592708945ed6821687ab5e7f99a7d937d6a5c93", + "key": "3132784670387270355134664e3261577974774f", "value": "76616c75655f666f725f3132784670387270355134664e3261577974774f" }, { - "key": "10afae10cb45e26a4ff4fe5ed2625de6b8171f00acef0a473fab915a2dd84f77", + "key": "324a69467553376255364f56343448423558524d", "value": "76616c75655f666f725f324a69467553376255364f56343448423558524d" }, { - "key": "7ff463bd7f1f977b6fcb2b0d09dc84b56a7e8a7533c3b7619bb77de8691500fe", + "key": "637250313164794e664e506a3945484842753030", "value": "76616c75655f666f725f637250313164794e664e506a3945484842753030" }, { - "key": "4b26caa4ea17fbecc86c3b18d9e9a60f5e9bb3f8df77bf886b23314de612b5ae", + "key": "5a78556e76433766477562364539325034455361", "value": "76616c75655f666f725f5a78556e76433766477562364539325034455361" }, { - "key": "1d042634447135086099546f3cb98b482bf913f2be2bfeabc1fd828c842b6915", + "key": "3256386d7459664e6e3644566f556866636f516e", "value": "76616c75655f666f725f3256386d7459664e6e3644566f556866636f516e" }, { - "key": "72a9edf278b5e09c2d3c9526f1345b1c862a9ead8e1a95621629b139684be33c", + "key": "504e4a4276453936456c66326559513643643939", "value": "76616c75655f666f725f504e4a4276453936456c66326559513643643939" } ], - "proof": "22b3430a5f0a5d0a20002c041fe1df37d806cc5b493bed02222d83b25ffebf9cb529b4524cc547fbeb121e76616c75655f666f725f636c536e4d46714a4e6162776a7a5134356e6d4d1a07080118012a01002210000102020102030405060708090a0b0c0a5b0a590a20fffa9eb3a5e49b7261d86e27c0e1c17f39215887308f5e3ca48e3264b03d2a2f121e76616c75655f666f725f6b63395874466e5a4645784d416f4b6f37566c5a1a07080118012a0100220c0d020e0f10111213141516170a600a5e0a20d905fdfb0063d1ae1cfb60037460005c24e77d0214d3f88f17e44ccfa302c533121e76616c75655f666f725f426f4c4f5279574251784c695835754c7257524a1a07080118012a0100221118190102011a1b1c1d1e1f2021222316170a590a570a2085e3ed5362f3659ec475645ad63d9f23a1ce81cfdcbd17318768ea8133871a7d121e76616c75655f666f725f483977566967584c6d3330756f726a4b534233711a07080118012a0100220a2425262728292a2b2c170a5b0a590a203df3a2ba5c2e903ce8a4f8fe8dda64f5973de99cdea4361a4873a00e0783ee06121e76616c75655f666f725f687848476735394278645a7256575756473662391a07080118012a0100220c2d02022e2f30313233340b0c0a5b0a590a20a66a205c2b5a6101ceb0c39823500f9b10681e2c4ae2efa5f977a871faf77b1d121e76616c75655f666f725f6f62695655544657735949374a7a6c62654e30741a07080118012a0100220c35363738393a3b3c3d3e2c170a5b0a590a2016659734ab7c95e3043ae7896fea9191a6a4d79186ea87e11c0414c2511d7e7f121e76616c75655f666f725f683139594138737249614956386b5579363156721a07080118012a0100220c3f40414243444546470a0b0c0a5b0a590a20b2943d32dde246b9140e0d97dbb1061ea681a385eca7abcc6d6b2b88ba4d5dbd121e76616c75655f666f725f6e586b6e744366514d53436a39625963516e325a1a07080118012a0100220c48494a4b4c4d4e4f503e2c170a5b0a590a2050ce16abe59462be0c5e6c67c865a281b91cf99d0e30bb324c97d69d611d9b70121e76616c75655f666f725f7542684a444c57425a7338765569786e6b3144491a07080118012a0100220c5152535455565758595a5b0c0a5b0a590a2035684a8bb5bab8674ec7e6f19efc5cac19a2d6df21b8156bf86f6e86ab19d2e1121e76616c75655f666f725f56336e7859534c6c4a6b3739646d776b3330634b1a07080118012a0100220c5c025d5e5f60616233340b0c0a590a570a20153b5591bd409f92b9ac8a997abaab4cd79b6c41f923b8541c3ba5a1dd26953f121e76616c75655f666f725f395277644d4b354e786d506942755950454e695a1a07080118012a0100220a636465664546470a0b0c0a5b0a590a20266c8f74eb0f2d19314153c5ec74aa343e79064bee1bd4280a5e3d2bb121dc27121e76616c75655f666f725f746b425246386e79314e4f35775244514d376c461a07080118012a0100220c670268696a6b6c6d6e340b0c0a590a570a20c7bcf000bd45ae83a6020d590a9d33cd29dfef1bdb2e98ba2482a489a48a8c13121e76616c75655f666f725f4e41334178576a42485233524b746a50713065751a07080118012a0100220a6f7071727374752316170a590a570a20d6f4d73207bcd05b9306710c8bd012bd198dd0383255ae72b56aa70850dfa1d6121e76616c75655f666f725f5559656353686a697731476b3942494b66686f6d1a07080118012a0100220a767778797a7b222316170a5b0a590a20a57e080d7762b2ba42323ac47592708945ed6821687ab5e7f99a7d937d6a5c93121e76616c75655f666f725f3132784670387270355134664e3261577974774f1a07080118012a0100220c7c7d7e7f80013b3c3d3e2c170a620a600a2010afae10cb45e26a4ff4fe5ed2625de6b8171f00acef0a473fab915a2dd84f77121e76616c75655f666f725f324a69467553376255364f56343448423558524d1a07080118012a01002213810101820101830184018501860146470a0b0c0a650a630a207ff463bd7f1f977b6fcb2b0d09dc84b56a7e8a7533c3b7619bb77de8691500fe121e76616c75655f666f725f637250313164794e664e506a39454848427530301a07080118012a0100221687010288010289018a018b018c018d018e018f015b0c0a650a630a204b26caa4ea17fbecc86c3b18d9e9a60f5e9bb3f8df77bf886b23314de612b5ae121e76616c75655f666f725f5a78556e764337664775623645393250344553611a07080118012a01002216900191010292019301940195019601970198015a5b0c0a660a640a201d042634447135086099546f3cb98b482bf913f2be2bfeabc1fd828c842b6915121e76616c75655f666f725f3256386d7459664e6e3644566f556866636f516e1a07080118012a010022179901019a019b019c019d019e019f01a001a101470a0b0c0a630a610a2072a9edf278b5e09c2d3c9526f1345b1c862a9ead8e1a95621629b139684be33c121e76616c75655f666f725f504e4a4276453936456c663265595136436439391a07080118012a01002214a2010201a301a401a501a601a7018e018f015b0c122708011201011a204c27b74a03394f254117dc2dd4aaa27ad2a3eccb0fa6f23dfc52eea501d133cd122708011201011a200000000000000000000000000000000000000000000000000000000000000000122508011221010000000000000000000000000000000000000000000000000000000000000000122708011201011a207a9e6f4327be207f312a80fecec582699f45b35e7fd2c3357c9c5ff7432f36f6122708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad122708011201011a202267b5ddaf71187e34cc533c3e7ee25dfd386a3698249a482c28b4c4016389f1122708011201011a20d80dd2a33eba727f1464bc6ae82a164d56f057cbcfd68e8e5e01b16d62ca28f8122708011201011a2024f1a08038cec03788d6692c5f6581ab50318277ed47932e6d3bcf750df64141122708011201011a20050961036298f28b550ce8123f9f9ccfefcaf1059808c2f285bd24915da7ca80122708011201011a20b735a57c73e8399b6c4105d07aab95b2a7ff7fa7dd6bb3ee40ad21d157c55b84122708011201011a20eaac481f8ac8418ee1eabde1459b6ff7369b5ce8c034d63fc0169d49f9827bb4122708011201011a20207bedb000df636941dfcd8393a399cca2f3eea7013beb04c8257e36aa11f03a122708011201011a20be47d8a61c2acd356be44e9c83ed51bfa13503fded1ea8965d1dd9a721d98f9f12250801122101b76263b0c4e8438e81f21cdbff1e21b894a3c0e4ea08a0deab7c1de3292cd16a122508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd1225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d31225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba1225080112210146eaec810967e45673028074c769ca2a8ddb3a5dbd47eab5cb6c5ccce3496eab122508011221013ff09e39daa0a77181976e045c441e4716144988ccf7cb308ef9820f40111437122508011221018228a63b956885383bb6168a8bc57b1edff829e2a2caee5200a600fbcc8b3d2512250801122101676d00d395acdcc0dec167c1a3ccf45fa415737faee5b74e8754df794a88b64d12250801122101ab73d025c6345f219bcc724c954729edaa496884d0f693c7645a8884fa0f298a1225080112210165a967ceeaf481cd2f5e2bc6d8f0435f5721b0739c3a4731f37ab11783133cbc122508011221011b8fec5bff949ff2c00ceed5c620f33c808249dccb408b623db89fa764a6ac5b12250801122101f46a611d5e06078694b314729936c2e52471923e187dbd5d71c74be963c22417122508011221012d2ed3841fb3fb2fdae10a427542a0a7e4932dc01c27c154c19610d205c3a22c122708011201011a208eeb8a660fbf34aeecaa4509aa72332a12beee8fc4e020938bb6ca1a69a4fbe5122708011201011a20cf24fd569b70a3903246200ff8f8d903eeaa2c5e35cffb65074bdcd7a4eb3b0c122708011201011a201862b3a21bd284386453f0734a4678b59b5411beee348419e2c138bce866709b122708011201011a2073b86c9d198aa201c55751b86fd99b341cfb288957cfb5270116a777993929d912250801122101cf53354a8ddd4d319a94a6505e41da6593291c434bdee02fada71d57cb432f3c122708011201011a20c43fb9e3554b3d229bb7a6633a4109a69cc926daff778ca7e1c80ee27ec1b283122708011201011a2054e7420dac859c97f26b8f0f73e4bf058ef2eaf6af66e63b27c02c3b33ad7adf122508011221013d0540608befb7ab726d97d0b44535a738ac3daa5cf362855a6060f56cd47a5c12250801122101a6900433c8bea8425e65d4fedf061073fa4f3c96d14b55272a6a4bee4112422d122708011201011a20133ce60dbeaff551d506eb85faf19a08d88c1aabc7a579b6a260b474bfe1976f122508011221013c6a80e5249148dd9db50e75bb37cc9bf00696a66af293ad42bb9fbbc1981c5012250801122101048117ba2b17332819e7b3afa6ee881356edf33fb28e78e5b555644d4db8109e12250801122101bd67b20b17090592c5f5eee64e8f9d24cd4807eb8d08224d730a25725ff105b2122708011201011a2038f93f3dbfd74b0545510d22698a4277cd2825fbf250efcf0db605fc12ec6319122508011221013d8771384f9457f041fa2259609025fb25480ead83819eb418050cc0079b133e122708011201011a202b2520f45c94631a59b98227c7747a212e4fcb5e4d524464c84e67ae67e1c28e122708011201011a20d4a6e9e4496a7cd271b0e307292f254b38499c76ab01dc848331527e069b093b122708011201011a20dbfb4b9dc45de4ba516bbbf08ddde13e5fa408500ef27423ad4d3a2147b7bea5122708011201011a2036e9058727831dbca632c540b911facabe0bb512ce623052f57fae7449be7a9d12250801122101ca23541c87a7f1c08e35aec96771b3c6e642a991a23f5a71982299237b9c7c1c1225080112210159d8ca1196e3cb12f21b1a275e58588d569c0253a3ce5bf19b5e29e08f8884b01225080112210199e76c784c50b3e2c1570d6d70fc98ef981ca02f85338d9900a1d52cbea46d01122708011201011a20e980532774bf16dceab254f91fcc05eedab3211ccc6c0d69f3717da1b9939478122508011221016744b9107f5be01d11cc98986bf40c7dd49bc257bf968a5b160b446cff18c8ab122508011221010693b77fd489e95f8cf1861fde23de6339cb359f1ecdf909c68b69843ab96e0a12250801122101058c30e22e96a0f99122609f4a6e50c6815240818eaddfa56c8ad9067da15e3512250801122101bfd69f527d0f170f15b1f4ac3bbaac0ca91560db2b77004722b9b94c2acc394b122708011201011a204128d7ac80e352269ece997a95565f9b606a4fa0890abf9b0cbf48e5a4eaad281225080112210160ad388ac451adb2074de377928b89211f49ae2d5f6e7b73c81035cfd2cfd709122508011221018c3d52acaf872248183fe11cd8f7541288040cd6ff05084e37ad92e94619f536122708011201011a20b3c4c041a69d63a5d978a67f6cffb1936dd81d43afec5e9c0aed9b34d4f931b4122708011201011a20a9e31a0ce8cfd15ffbed5aa7a32fd20e203f24cf5b7cc3ef05de2cdcf4f7529e122508011221011f7275251a725c43e8f9f829bc615ce3362ce8425af0cccd34643d72a5fa8b0b122508011221017562485b760afbcf9bdfa72c824f44b762187d254ad2526ef10731217cea0285122708011201011a202290d78dffcbd7c5d71e41ac7308d6a38ff8c4acef31f43e4ec08f9e9f13cb36122708011201011a2085bc034ff3b2d35bd6c722717f18cfb54aec81b93dd276ca2693f7553c80346c12250801122101ced5a0edfbcbb8e31f8bb407ee4b0adb3589d4212526f21fa96902a6cca63e39122708011201011a2024e0dc8ecb29d05f5e666ff9f48986369fa2cc4684945615d6a6e90c36676dcd122508011221012da3225bb1c80352a797e2a684dc842651368f0a4ce80de00d9d15b80bc0c89812250801122101483c72ce68ddcab1dc34b612173ef08a1e72e0f700e590742dc0377aca1a6433122708011201011a2053ef26fcc8a46af6cf1dfdbf40316ddf263c1bd507273e41e8c4107303343347122708011201011a20b9e15e2e63188aba2af500e8516cfebf7c65d9e038b0a4a442d774bcc05202971225080112210188f330dc91c6a3f114763242241dbc84fa5b80facb7f8a4ba249ec6e586eac6c122508011221016aa0a28b470b18ac7cf16ec89fe83cad82cfddcce596239f4414515575d8b422122708011201011a20cf58d802a5b45a1310985c5165c0870d54e17679917c590998aea8e7cc9b408012250801122101afa7971e8ac0609e2709ae13f218c83c632264c318291b2327c1e163305be47b12250801122101f32645861c9e82cf56bf46036d155b818c2cc2caa1bbcc7a43e836ce07d807ca122708011201011a2095f93afeb4bb39b73b8230931d17e78d2f4cc169c4bfec76f1d2f3a6fb21d0ff122708011201011a208ac52074530ae19b4ec74b68b18f8c667ef9769d25f95d7fa7f26e83533ae92112250801122101ebc209c74dae2128a7d333fc416d473b983ced345696e93ca927c81a18d95580122708011201011a2091ae2d65ad7c3dbb8beef46d09b6c5c3cdebe6e2c13317ccbf23169125a484f412250801122101b2b42e90de76bb2a06044a1aa5bf11fead5f5de8d4c74f8bc1a648921599bfdd122708011201011a20f8d08696b7dce82ddd748e84c8515d5d024aa7194124cd0b33655f6bd844705d122708011201011a20579c8ed83742c9bed43c204d30221f649ca130ccfb42dd857e5729b8a8e8a34f1225080112210155066699266cf25025b198ae536d48be0ee48a15a2f3dad9de43265be576bad8122708011201011a20401797c0f62b5f2e33337c584cfb78057e3bcb99f54815eb50ef359f26664a56122708011201011a20b77f3050d43d37012c9e96ba9e6fc532a4942ddde3ecdb5e4433bf24d7dd8b31122508011221015cd0738a9f9fbdabb5654c5d07469a2ed956c62d0a0b23df18e893db6904938512250801122101c3dd840575e9df89717bea07ab3aab4854f7008a3859d47e75eda84640427c0e122708011201011a20db586278ea6abb5683694e3d214c86e762709356ed2f44f8c9090ae7c95f1b77122708011201011a206b2f11e284032cf7920a95ea4b28434e3c37b95fea292684bfdf99cc25610db1122708011201011a206056323234df9abbeb02389c808c4f90f94a8705c6fae3cba93483410e30dda8122708011201011a20bd4eb1a98ba8e2fcb5b2c51f243cd217147e89eae0c93465042b264298e8af6312250801122101e03bc85478a74a95761b1d2a9438bd7341ae5532f171be75128907f45e027d9f122708011201011a20986ab3a15460d46f0ed38afbe9387d768fe219c118d0ccf70577ba4f12c3ec9612250801122101a490bedac9cc306dc7721bde73b8416e9f9564a298d1b2d37410a3f90135c216122708011201011a202e6b805bb42e7eea0487251c2332f61fd9ac55926a3e668251ae1f23d3a812a512250801122101b1222b2963878020e021dd28d2df05b4f8307084d13029c3915865f84afd56c0122708011201011a20efbef68b9a5b015b4a00d10037bb66ad245b5e30861eb64696934d889baea1a7122508011221018c24741b30a9c36ba0fcd873f4e21d98a80b8040761e2ea2d34332eeed6ee81b122708011201011a20b5a93de5e8dda4769f9c3397dd4b2638e7a437263f29f58de02d0d17932e449012250801122101ff1322a499933052c2e966eb031fc912d71ddbdde3a369f76ac826bfe05a27c8122708011201011a207c1990a63b7833bfd1d390e2e782483593dcef7067e4f587d6929bb48a3a2b03122708011201011a20b2c66013204af0eda043edb68c51524bc675b4fae5f6510af7eefe12b14ddd78122708011201011a2031825b5f7715b2a91d296b932050295634a3b922ef10922f6291ae7e9faef67f122508011221016cc9226a6d6f383c45f3912f9e0a2d4be5dfdfdbee09e04743d2fb22660d37ce122708011201011a20122193d0faace84387851c6dc891694f8d2ed47f41dba25881379197301a27aa122708011201011a2055b48726e5f1f8aecfece9471c8c6cce0a4ba4f5f77c7c611a097fa0fead749c12250801122101019363b91ed17ce573438eb65bbda4ea0e5482fda22bd96ed91a330bdf313c46122708011201011a205e053c924a657d6edd8810c12eddceee548ac86057f66a72e67745d0c03af09e122708011201011a204eb906b4d01cc39e57d88b28102cf543be7421282081b9fb727b2bba31f10bb7122508011221017a58369140367959e1cf1009e8b71d4c0d62a079a9bf0102f330aaf245cb13ed1225080112210119a4d2d17a37faf0605c8ac65cb4aac72de3d7779c64c8b78577df090685d442122708011201011a206db2b5ae7a1de14f4a8f779f0f12a4b67357945d3c15ecd7271aaf07a74e2dfa122708011201011a20d19a3c11a42b447b179bcfc7431a943cc3f597981a6c6dd91f994e1901e752d4122708011201011a20998c71664d07489f1856c64ab887a857547ac89df9a86c6b92da530cc36ec36c12250801122101076db06367bceb7bcc32067228a106cee4f2c8e6ea3c89cb71e47c9c248266281225080112210132606896f001c9d8dcd265d930d18e94582a3d52fb030da76a5dbb8f1cbcd432122508011221018aca2c209020a57524148ccab47c928969956a5978b2b6031dfe3580373065f912250801122101ce7c5c7aae73f63bdb4aee0d33ce99d1bbf659fc0d3caf444529c5bb015d66a3122708011201011a207829c213824cc50a7705b799054a848decd28dd78183683ec6b3b57e1a207f5d122708011201011a20b0d25f9fe186304e97f7a1892ac21caa48deac5750adba83e8e7a3ab68ae294e1225080112210145931a787b170595efe766b69445c8fff0f34bb32aa09c25c1fd832e25f9dbe31225080112210102a3bd7d067f1dd1e320c2cab008c73fcb9e090122ecd9510a1fd70408ddd61b122708011201011a2029c314de40783a3b5b2b0b0c9c0b2fd2cdc1fc85e1f9565a5e5d0577711f501c122508011221015a4b2962e8c1ec371e6e3cdc01f3e7385c77c6321bd995024a9e69ed3b90033712250801122101fafc67202686918c548c03e413e266a9178e61c3b7dd50b3cd058d2a78a646d5122708011201011a203978d57f079ea09d6d6d32710f019c4b09315375ed3ce1173e0667becb564c9312250801122101921da87ca3b5fcb796e07a7fbf7580e6d8c72e90d33e1bd46974c9360b45454412250801122101ad4ae81872a0132f51cd6ea883426f7e00030aec8c12779493007478ed85deac122708011201011a205302d42be40f87ac957be75c3c668ad4c91bae6eb1ed56e26c0d60eefba964fa122508011221013f1c8d8acbb5c8ad98797ba5e046bf6670121e97a351ba0781c6386d9afd8bbe122708011201011a20f8ff09744ca36902b580c24ca166418affc46818120d1d435b2d09bd8448317612250801122101e7fa82c24f93c1690f3e564b0a3f1b45eaed3c8f06bdcbc59a1fa416d7d5c820122508011221019efbbbf59c7ed77a5d3dc61b8b6f77178c2a2ed3ba6dc7fa61fffde02d19d3ee1225080112210185e5a25bf7906404130d2b57db9e68d8192919cf0ff186e694b1b019fd58ac88122708011201011a20388c501b4bda0c64c0a85d74d9ad1e7608de52b067a5d893ad83042aa0ffe5ad122708011201011a207b652e83c4d49c7f9476079ebde01742b61f724d51b8550d44ad2fa16e7d1044122708011201011a20879c5704e1df82bba5645ab26fce2d587d5a6f02079d0f43c349e9a4535672b8122708011201011a20f1ff26854e0c6e83717c88f7e4cee8369d046dbd9bacbdb6f278d2e29cf1135f122508011221016b905beec1e895cd07612a113f10a8a941391e4cf6c1c3319db4e00904e19bfd1225080112210171b33a17bab7756fc50d898e77689f22c2b6819ca0ca4bf53d57b6d080dc24d4122508011221018c9dedcadf0b0fb4013aca1a520143bdb24afda97fa33cc6e6c426648b2d641e12250801122101d41a8431fa556ce77f080be32758a8186d9544886e969b7341031982cbee336b12250801122101919dc73a4d6f20bb5fe14a4bbd57c1c58c52ac9ecd9cc167d1e4b0b013d9c264122508011221017f42ba0ab9cf7c3328509a669ff3f005fff65768eda3c78a08b507aa291e9f6d12250801122101550e4a13c7e10998bd0f28e012103c375eb83d02f870868e199a7c32d741c9b012250801122101ad81a0c099cd1f93e449fa2f4aa848c28e34fb0e4abc32d88fa05507418592cd122708011201011a20263b61b05d34033be1a2337b31aaab56b45283006b7c726b5bff4927810a9a77122708011201011a20900384b9152038b0ea841ab3fdd1719a75f60556fd7444c7c75b50111bdbf939122708011201011a203fe233a95d2d4cfde64850c9ff8280b74d060f6a575267cb78269709aaad7cd0122708011201011a201a6e8fc11ab2f3eb98d93c19ddb1534dd2753266373b7549ed3e2cb98adac735122508011221018384754befba9655eacc0c46ccb0c72344b710c4bf6ab42883fb0709634a4c4c1225080112210131734bd84fbc3542040ec104a6ab5378b8f5106ab621ee42f9f8f42e18a0db94122708011201011a20853799f77971e980c5f85e3e69b5bc3e7c86c223ba99395899f070fa0a14949912250801122101c4c4b88cd764772b9a4129ff4f9be42f795624b85f043b17afff7862bbc4ba9a122708011201011a204a1f1d9534fd0fe7df108acb235054232bf7378508c6f10dec6fe47bc01d151d12250801122101186fa2307c9f24158c61639492143e8940a466163d056c22db6cb8c0655af90a122708011201011a203313bb9fb8c001cf54523a2c896d1cad8d0a1c5ac12547c3bd66e93aa16345c0122708011201011a205d0119e99e0c4ffed7df85ccd6d3526d8ef09b1c352c21b2d520c4bbaa246f04122708011201011a203317850ab321269b8658e79bc7e07a5b5fd8335989d802c6610092fef9d7a875122708011201011a200f2c5d4672c826239e69174d3656f0d849ac37dd7c321504e409a26488a2d3d6122508011221019f1f6aa3dbfb07ce8a770510115ba4a0c8738586999c74fb01d07a407c796241122708011201011a20041132c96dc3eaacca49829e001dbc8728103125ee73c503ead0bacc861c774612250801122101c961801e9e3011097a7edc58adda84f3807c74f16cd8b41c6616db13d4a86c471225080112210195d4fff097a4a5b299f8b6c0d3ee99dae37d0170d53df7b32fd37361204cde08122708011201011a20dd19d74f3c321ae47274865e9e4ad151205f51f42fd46144f8b9876c8416479512250801122101a88bda4f1ebf49b72ee3db9b4851df750d8a1286c76ce585b376570ccd49ac68122708011201011a20903838cfa8d373a9fe71cdb27ea7d846f89b7ccb74fc2a963ea06f3af47c15df1225080112210155bb3c92cd308e1939fa9e96a05f072dc4b46a08a5a99eef7ee8c731e820f058122708011201011a209557e9d2ba170d82b0479ba3fdd6c26b846ed8c82d41725c39ec9c82adb42db8122708011201011a20188a65398211152f6c6c86f54023c3a1fb9b2f0b5d63d8f1bc9cd93daaffae94", + "proof": "22eb410a550a530a14636c536e4d46714a4e6162776a7a5134356e6d4d121e76616c75655f666f725f636c536e4d46714a4e6162776a7a5134356e6d4d1a090801100118012a01002210000102020102030405060708090a0b0c0a510a4f0a146b63395874466e5a4645784d416f4b6f37566c5a121e76616c75655f666f725f6b63395874466e5a4645784d416f4b6f37566c5a1a090801100118012a0100220c0d020e0f10111213141516170a560a540a14426f4c4f5279574251784c695835754c7257524a121e76616c75655f666f725f426f4c4f5279574251784c695835754c7257524a1a090801100118012a0100221118190102011a1b1c1d1e1f2021222316170a4f0a4d0a14483977566967584c6d3330756f726a4b53423371121e76616c75655f666f725f483977566967584c6d3330756f726a4b534233711a090801100118012a0100220a2425262728292a2b2c170a510a4f0a14687848476735394278645a725657575647366239121e76616c75655f666f725f687848476735394278645a7256575756473662391a090801100118012a0100220c2d02022e2f30313233340b0c0a510a4f0a146f62695655544657735949374a7a6c62654e3074121e76616c75655f666f725f6f62695655544657735949374a7a6c62654e30741a090801100118012a0100220c35363738393a3b3c3d3e2c170a510a4f0a14683139594138737249614956386b557936315672121e76616c75655f666f725f683139594138737249614956386b5579363156721a090801100118012a0100220c3f40414243444546470a0b0c0a510a4f0a146e586b6e744366514d53436a39625963516e325a121e76616c75655f666f725f6e586b6e744366514d53436a39625963516e325a1a090801100118012a0100220c48494a4b4c4d4e4f503e2c170a510a4f0a147542684a444c57425a7338765569786e6b314449121e76616c75655f666f725f7542684a444c57425a7338765569786e6b3144491a090801100118012a0100220c5152535455565758595a5b0c0a510a4f0a1456336e7859534c6c4a6b3739646d776b3330634b121e76616c75655f666f725f56336e7859534c6c4a6b3739646d776b3330634b1a090801100118012a0100220c5c025d5e5f60616233340b0c0a4f0a4d0a14395277644d4b354e786d506942755950454e695a121e76616c75655f666f725f395277644d4b354e786d506942755950454e695a1a090801100118012a0100220a636465664546470a0b0c0a510a4f0a14746b425246386e79314e4f35775244514d376c46121e76616c75655f666f725f746b425246386e79314e4f35775244514d376c461a090801100118012a0100220c670268696a6b6c6d6e340b0c0a4f0a4d0a144e41334178576a42485233524b746a5071306575121e76616c75655f666f725f4e41334178576a42485233524b746a50713065751a090801100118012a0100220a6f7071727374752316170a4f0a4d0a145559656353686a697731476b3942494b66686f6d121e76616c75655f666f725f5559656353686a697731476b3942494b66686f6d1a090801100118012a0100220a767778797a7b222316170a510a4f0a143132784670387270355134664e3261577974774f121e76616c75655f666f725f3132784670387270355134664e3261577974774f1a090801100118012a0100220c7c7d7e7f80013b3c3d3e2c170a580a560a14324a69467553376255364f56343448423558524d121e76616c75655f666f725f324a69467553376255364f56343448423558524d1a090801100118012a01002213810101820101830184018501860146470a0b0c0a5b0a590a14637250313164794e664e506a3945484842753030121e76616c75655f666f725f637250313164794e664e506a39454848427530301a090801100118012a0100221687010288010289018a018b018c018d018e018f015b0c0a5b0a590a145a78556e76433766477562364539325034455361121e76616c75655f666f725f5a78556e764337664775623645393250344553611a090801100118012a01002216900191010292019301940195019601970198015a5b0c0a5c0a5a0a143256386d7459664e6e3644566f556866636f516e121e76616c75655f666f725f3256386d7459664e6e3644566f556866636f516e1a090801100118012a010022179901019a019b019c019d019e019f01a001a101470a0b0c0a590a570a14504e4a4276453936456c66326559513643643939121e76616c75655f666f725f504e4a4276453936456c663265595136436439391a090801100118012a01002214a2010201a301a401a501a601a7018e018f015b0c122708011201011a204c27b74a03394f254117dc2dd4aaa27ad2a3eccb0fa6f23dfc52eea501d133cd122708011201011a200000000000000000000000000000000000000000000000000000000000000000122508011221010000000000000000000000000000000000000000000000000000000000000000122708011201011a207a9e6f4327be207f312a80fecec582699f45b35e7fd2c3357c9c5ff7432f36f6122708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad122708011201011a202267b5ddaf71187e34cc533c3e7ee25dfd386a3698249a482c28b4c4016389f1122708011201011a20d80dd2a33eba727f1464bc6ae82a164d56f057cbcfd68e8e5e01b16d62ca28f8122708011201011a2024f1a08038cec03788d6692c5f6581ab50318277ed47932e6d3bcf750df64141122708011201011a20050961036298f28b550ce8123f9f9ccfefcaf1059808c2f285bd24915da7ca80122708011201011a20b735a57c73e8399b6c4105d07aab95b2a7ff7fa7dd6bb3ee40ad21d157c55b84122708011201011a20eaac481f8ac8418ee1eabde1459b6ff7369b5ce8c034d63fc0169d49f9827bb4122708011201011a20207bedb000df636941dfcd8393a399cca2f3eea7013beb04c8257e36aa11f03a122708011201011a20be47d8a61c2acd356be44e9c83ed51bfa13503fded1ea8965d1dd9a721d98f9f12250801122101b76263b0c4e8438e81f21cdbff1e21b894a3c0e4ea08a0deab7c1de3292cd16a122508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd1225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d31225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba1225080112210146eaec810967e45673028074c769ca2a8ddb3a5dbd47eab5cb6c5ccce3496eab122508011221013ff09e39daa0a77181976e045c441e4716144988ccf7cb308ef9820f40111437122508011221018228a63b956885383bb6168a8bc57b1edff829e2a2caee5200a600fbcc8b3d2512250801122101676d00d395acdcc0dec167c1a3ccf45fa415737faee5b74e8754df794a88b64d12250801122101ab73d025c6345f219bcc724c954729edaa496884d0f693c7645a8884fa0f298a1225080112210165a967ceeaf481cd2f5e2bc6d8f0435f5721b0739c3a4731f37ab11783133cbc122508011221011b8fec5bff949ff2c00ceed5c620f33c808249dccb408b623db89fa764a6ac5b12250801122101f46a611d5e06078694b314729936c2e52471923e187dbd5d71c74be963c22417122508011221012d2ed3841fb3fb2fdae10a427542a0a7e4932dc01c27c154c19610d205c3a22c122708011201011a208eeb8a660fbf34aeecaa4509aa72332a12beee8fc4e020938bb6ca1a69a4fbe5122708011201011a20cf24fd569b70a3903246200ff8f8d903eeaa2c5e35cffb65074bdcd7a4eb3b0c122708011201011a201862b3a21bd284386453f0734a4678b59b5411beee348419e2c138bce866709b122708011201011a2073b86c9d198aa201c55751b86fd99b341cfb288957cfb5270116a777993929d912250801122101cf53354a8ddd4d319a94a6505e41da6593291c434bdee02fada71d57cb432f3c122708011201011a20c43fb9e3554b3d229bb7a6633a4109a69cc926daff778ca7e1c80ee27ec1b283122708011201011a2054e7420dac859c97f26b8f0f73e4bf058ef2eaf6af66e63b27c02c3b33ad7adf122508011221013d0540608befb7ab726d97d0b44535a738ac3daa5cf362855a6060f56cd47a5c12250801122101a6900433c8bea8425e65d4fedf061073fa4f3c96d14b55272a6a4bee4112422d122708011201011a20133ce60dbeaff551d506eb85faf19a08d88c1aabc7a579b6a260b474bfe1976f122508011221013c6a80e5249148dd9db50e75bb37cc9bf00696a66af293ad42bb9fbbc1981c5012250801122101048117ba2b17332819e7b3afa6ee881356edf33fb28e78e5b555644d4db8109e12250801122101bd67b20b17090592c5f5eee64e8f9d24cd4807eb8d08224d730a25725ff105b2122708011201011a2038f93f3dbfd74b0545510d22698a4277cd2825fbf250efcf0db605fc12ec6319122508011221013d8771384f9457f041fa2259609025fb25480ead83819eb418050cc0079b133e122708011201011a202b2520f45c94631a59b98227c7747a212e4fcb5e4d524464c84e67ae67e1c28e122708011201011a20d4a6e9e4496a7cd271b0e307292f254b38499c76ab01dc848331527e069b093b122708011201011a20dbfb4b9dc45de4ba516bbbf08ddde13e5fa408500ef27423ad4d3a2147b7bea5122708011201011a2036e9058727831dbca632c540b911facabe0bb512ce623052f57fae7449be7a9d12250801122101ca23541c87a7f1c08e35aec96771b3c6e642a991a23f5a71982299237b9c7c1c1225080112210159d8ca1196e3cb12f21b1a275e58588d569c0253a3ce5bf19b5e29e08f8884b01225080112210199e76c784c50b3e2c1570d6d70fc98ef981ca02f85338d9900a1d52cbea46d01122708011201011a20e980532774bf16dceab254f91fcc05eedab3211ccc6c0d69f3717da1b9939478122508011221016744b9107f5be01d11cc98986bf40c7dd49bc257bf968a5b160b446cff18c8ab122508011221010693b77fd489e95f8cf1861fde23de6339cb359f1ecdf909c68b69843ab96e0a12250801122101058c30e22e96a0f99122609f4a6e50c6815240818eaddfa56c8ad9067da15e3512250801122101bfd69f527d0f170f15b1f4ac3bbaac0ca91560db2b77004722b9b94c2acc394b122708011201011a204128d7ac80e352269ece997a95565f9b606a4fa0890abf9b0cbf48e5a4eaad281225080112210160ad388ac451adb2074de377928b89211f49ae2d5f6e7b73c81035cfd2cfd709122508011221018c3d52acaf872248183fe11cd8f7541288040cd6ff05084e37ad92e94619f536122708011201011a20b3c4c041a69d63a5d978a67f6cffb1936dd81d43afec5e9c0aed9b34d4f931b4122708011201011a20a9e31a0ce8cfd15ffbed5aa7a32fd20e203f24cf5b7cc3ef05de2cdcf4f7529e122508011221011f7275251a725c43e8f9f829bc615ce3362ce8425af0cccd34643d72a5fa8b0b122508011221017562485b760afbcf9bdfa72c824f44b762187d254ad2526ef10731217cea0285122708011201011a202290d78dffcbd7c5d71e41ac7308d6a38ff8c4acef31f43e4ec08f9e9f13cb36122708011201011a2085bc034ff3b2d35bd6c722717f18cfb54aec81b93dd276ca2693f7553c80346c12250801122101ced5a0edfbcbb8e31f8bb407ee4b0adb3589d4212526f21fa96902a6cca63e39122708011201011a2024e0dc8ecb29d05f5e666ff9f48986369fa2cc4684945615d6a6e90c36676dcd122508011221012da3225bb1c80352a797e2a684dc842651368f0a4ce80de00d9d15b80bc0c89812250801122101483c72ce68ddcab1dc34b612173ef08a1e72e0f700e590742dc0377aca1a6433122708011201011a2053ef26fcc8a46af6cf1dfdbf40316ddf263c1bd507273e41e8c4107303343347122708011201011a20b9e15e2e63188aba2af500e8516cfebf7c65d9e038b0a4a442d774bcc05202971225080112210188f330dc91c6a3f114763242241dbc84fa5b80facb7f8a4ba249ec6e586eac6c122508011221016aa0a28b470b18ac7cf16ec89fe83cad82cfddcce596239f4414515575d8b422122708011201011a20cf58d802a5b45a1310985c5165c0870d54e17679917c590998aea8e7cc9b408012250801122101afa7971e8ac0609e2709ae13f218c83c632264c318291b2327c1e163305be47b12250801122101f32645861c9e82cf56bf46036d155b818c2cc2caa1bbcc7a43e836ce07d807ca122708011201011a2095f93afeb4bb39b73b8230931d17e78d2f4cc169c4bfec76f1d2f3a6fb21d0ff122708011201011a208ac52074530ae19b4ec74b68b18f8c667ef9769d25f95d7fa7f26e83533ae92112250801122101ebc209c74dae2128a7d333fc416d473b983ced345696e93ca927c81a18d95580122708011201011a2091ae2d65ad7c3dbb8beef46d09b6c5c3cdebe6e2c13317ccbf23169125a484f412250801122101b2b42e90de76bb2a06044a1aa5bf11fead5f5de8d4c74f8bc1a648921599bfdd122708011201011a20f8d08696b7dce82ddd748e84c8515d5d024aa7194124cd0b33655f6bd844705d122708011201011a20579c8ed83742c9bed43c204d30221f649ca130ccfb42dd857e5729b8a8e8a34f1225080112210155066699266cf25025b198ae536d48be0ee48a15a2f3dad9de43265be576bad8122708011201011a20401797c0f62b5f2e33337c584cfb78057e3bcb99f54815eb50ef359f26664a56122708011201011a20b77f3050d43d37012c9e96ba9e6fc532a4942ddde3ecdb5e4433bf24d7dd8b31122508011221015cd0738a9f9fbdabb5654c5d07469a2ed956c62d0a0b23df18e893db6904938512250801122101c3dd840575e9df89717bea07ab3aab4854f7008a3859d47e75eda84640427c0e122708011201011a20db586278ea6abb5683694e3d214c86e762709356ed2f44f8c9090ae7c95f1b77122708011201011a206b2f11e284032cf7920a95ea4b28434e3c37b95fea292684bfdf99cc25610db1122708011201011a206056323234df9abbeb02389c808c4f90f94a8705c6fae3cba93483410e30dda8122708011201011a20bd4eb1a98ba8e2fcb5b2c51f243cd217147e89eae0c93465042b264298e8af6312250801122101e03bc85478a74a95761b1d2a9438bd7341ae5532f171be75128907f45e027d9f122708011201011a20986ab3a15460d46f0ed38afbe9387d768fe219c118d0ccf70577ba4f12c3ec9612250801122101a490bedac9cc306dc7721bde73b8416e9f9564a298d1b2d37410a3f90135c216122708011201011a202e6b805bb42e7eea0487251c2332f61fd9ac55926a3e668251ae1f23d3a812a512250801122101b1222b2963878020e021dd28d2df05b4f8307084d13029c3915865f84afd56c0122708011201011a20efbef68b9a5b015b4a00d10037bb66ad245b5e30861eb64696934d889baea1a7122508011221018c24741b30a9c36ba0fcd873f4e21d98a80b8040761e2ea2d34332eeed6ee81b122708011201011a20b5a93de5e8dda4769f9c3397dd4b2638e7a437263f29f58de02d0d17932e449012250801122101ff1322a499933052c2e966eb031fc912d71ddbdde3a369f76ac826bfe05a27c8122708011201011a207c1990a63b7833bfd1d390e2e782483593dcef7067e4f587d6929bb48a3a2b03122708011201011a20b2c66013204af0eda043edb68c51524bc675b4fae5f6510af7eefe12b14ddd78122708011201011a2031825b5f7715b2a91d296b932050295634a3b922ef10922f6291ae7e9faef67f122508011221016cc9226a6d6f383c45f3912f9e0a2d4be5dfdfdbee09e04743d2fb22660d37ce122708011201011a20122193d0faace84387851c6dc891694f8d2ed47f41dba25881379197301a27aa122708011201011a2055b48726e5f1f8aecfece9471c8c6cce0a4ba4f5f77c7c611a097fa0fead749c12250801122101019363b91ed17ce573438eb65bbda4ea0e5482fda22bd96ed91a330bdf313c46122708011201011a205e053c924a657d6edd8810c12eddceee548ac86057f66a72e67745d0c03af09e122708011201011a204eb906b4d01cc39e57d88b28102cf543be7421282081b9fb727b2bba31f10bb7122508011221017a58369140367959e1cf1009e8b71d4c0d62a079a9bf0102f330aaf245cb13ed1225080112210119a4d2d17a37faf0605c8ac65cb4aac72de3d7779c64c8b78577df090685d442122708011201011a206db2b5ae7a1de14f4a8f779f0f12a4b67357945d3c15ecd7271aaf07a74e2dfa122708011201011a20d19a3c11a42b447b179bcfc7431a943cc3f597981a6c6dd91f994e1901e752d4122708011201011a20998c71664d07489f1856c64ab887a857547ac89df9a86c6b92da530cc36ec36c12250801122101076db06367bceb7bcc32067228a106cee4f2c8e6ea3c89cb71e47c9c248266281225080112210132606896f001c9d8dcd265d930d18e94582a3d52fb030da76a5dbb8f1cbcd432122508011221018aca2c209020a57524148ccab47c928969956a5978b2b6031dfe3580373065f912250801122101ce7c5c7aae73f63bdb4aee0d33ce99d1bbf659fc0d3caf444529c5bb015d66a3122708011201011a207829c213824cc50a7705b799054a848decd28dd78183683ec6b3b57e1a207f5d122708011201011a20b0d25f9fe186304e97f7a1892ac21caa48deac5750adba83e8e7a3ab68ae294e1225080112210145931a787b170595efe766b69445c8fff0f34bb32aa09c25c1fd832e25f9dbe31225080112210102a3bd7d067f1dd1e320c2cab008c73fcb9e090122ecd9510a1fd70408ddd61b122708011201011a2029c314de40783a3b5b2b0b0c9c0b2fd2cdc1fc85e1f9565a5e5d0577711f501c122508011221015a4b2962e8c1ec371e6e3cdc01f3e7385c77c6321bd995024a9e69ed3b90033712250801122101fafc67202686918c548c03e413e266a9178e61c3b7dd50b3cd058d2a78a646d5122708011201011a203978d57f079ea09d6d6d32710f019c4b09315375ed3ce1173e0667becb564c9312250801122101921da87ca3b5fcb796e07a7fbf7580e6d8c72e90d33e1bd46974c9360b45454412250801122101ad4ae81872a0132f51cd6ea883426f7e00030aec8c12779493007478ed85deac122708011201011a205302d42be40f87ac957be75c3c668ad4c91bae6eb1ed56e26c0d60eefba964fa122508011221013f1c8d8acbb5c8ad98797ba5e046bf6670121e97a351ba0781c6386d9afd8bbe122708011201011a20f8ff09744ca36902b580c24ca166418affc46818120d1d435b2d09bd8448317612250801122101e7fa82c24f93c1690f3e564b0a3f1b45eaed3c8f06bdcbc59a1fa416d7d5c820122508011221019efbbbf59c7ed77a5d3dc61b8b6f77178c2a2ed3ba6dc7fa61fffde02d19d3ee1225080112210185e5a25bf7906404130d2b57db9e68d8192919cf0ff186e694b1b019fd58ac88122708011201011a20388c501b4bda0c64c0a85d74d9ad1e7608de52b067a5d893ad83042aa0ffe5ad122708011201011a207b652e83c4d49c7f9476079ebde01742b61f724d51b8550d44ad2fa16e7d1044122708011201011a20879c5704e1df82bba5645ab26fce2d587d5a6f02079d0f43c349e9a4535672b8122708011201011a20f1ff26854e0c6e83717c88f7e4cee8369d046dbd9bacbdb6f278d2e29cf1135f122508011221016b905beec1e895cd07612a113f10a8a941391e4cf6c1c3319db4e00904e19bfd1225080112210171b33a17bab7756fc50d898e77689f22c2b6819ca0ca4bf53d57b6d080dc24d4122508011221018c9dedcadf0b0fb4013aca1a520143bdb24afda97fa33cc6e6c426648b2d641e12250801122101d41a8431fa556ce77f080be32758a8186d9544886e969b7341031982cbee336b12250801122101919dc73a4d6f20bb5fe14a4bbd57c1c58c52ac9ecd9cc167d1e4b0b013d9c264122508011221017f42ba0ab9cf7c3328509a669ff3f005fff65768eda3c78a08b507aa291e9f6d12250801122101550e4a13c7e10998bd0f28e012103c375eb83d02f870868e199a7c32d741c9b012250801122101ad81a0c099cd1f93e449fa2f4aa848c28e34fb0e4abc32d88fa05507418592cd122708011201011a20263b61b05d34033be1a2337b31aaab56b45283006b7c726b5bff4927810a9a77122708011201011a20900384b9152038b0ea841ab3fdd1719a75f60556fd7444c7c75b50111bdbf939122708011201011a203fe233a95d2d4cfde64850c9ff8280b74d060f6a575267cb78269709aaad7cd0122708011201011a201a6e8fc11ab2f3eb98d93c19ddb1534dd2753266373b7549ed3e2cb98adac735122508011221018384754befba9655eacc0c46ccb0c72344b710c4bf6ab42883fb0709634a4c4c1225080112210131734bd84fbc3542040ec104a6ab5378b8f5106ab621ee42f9f8f42e18a0db94122708011201011a20853799f77971e980c5f85e3e69b5bc3e7c86c223ba99395899f070fa0a14949912250801122101c4c4b88cd764772b9a4129ff4f9be42f795624b85f043b17afff7862bbc4ba9a122708011201011a204a1f1d9534fd0fe7df108acb235054232bf7378508c6f10dec6fe47bc01d151d12250801122101186fa2307c9f24158c61639492143e8940a466163d056c22db6cb8c0655af90a122708011201011a203313bb9fb8c001cf54523a2c896d1cad8d0a1c5ac12547c3bd66e93aa16345c0122708011201011a205d0119e99e0c4ffed7df85ccd6d3526d8ef09b1c352c21b2d520c4bbaa246f04122708011201011a203317850ab321269b8658e79bc7e07a5b5fd8335989d802c6610092fef9d7a875122708011201011a200f2c5d4672c826239e69174d3656f0d849ac37dd7c321504e409a26488a2d3d6122508011221019f1f6aa3dbfb07ce8a770510115ba4a0c8738586999c74fb01d07a407c796241122708011201011a20041132c96dc3eaacca49829e001dbc8728103125ee73c503ead0bacc861c774612250801122101c961801e9e3011097a7edc58adda84f3807c74f16cd8b41c6616db13d4a86c471225080112210195d4fff097a4a5b299f8b6c0d3ee99dae37d0170d53df7b32fd37361204cde08122708011201011a20dd19d74f3c321ae47274865e9e4ad151205f51f42fd46144f8b9876c8416479512250801122101a88bda4f1ebf49b72ee3db9b4851df750d8a1286c76ce585b376570ccd49ac68122708011201011a20903838cfa8d373a9fe71cdb27ea7d846f89b7ccb74fc2a963ea06f3af47c15df1225080112210155bb3c92cd308e1939fa9e96a05f072dc4b46a08a5a99eef7ee8c731e820f058122708011201011a209557e9d2ba170d82b0479ba3fdd6c26b846ed8c82d41725c39ec9c82adb42db8122708011201011a20188a65398211152f6c6c86f54023c3a1fb9b2f0b5d63d8f1bc9cd93daaffae94", "root": "719e886178d2b75293341221dcbf83e81b7413c8c044790591a21cb3539ae8bb" } diff --git a/testdata/smt/batch_nonexist.json b/testdata/smt/batch_nonexist.json index b8717004..3a900aad 100644 --- a/testdata/smt/batch_nonexist.json +++ b/testdata/smt/batch_nonexist.json @@ -1,86 +1,86 @@ { "items": [ { - "key": "000da5e41c5fdd943b480cc680a1942d6708140827650e8e551df7b761bf5679", + "key": "674f686e5158505448496155356d303175434178", "value": "" }, { - "key": "ffffedc8e4ee7f13c9892bf6277cdd60e4e8fad77abb37ca4f3b888a63b60df4", + "key": "68316d656864356a774f646f4f4264613530684e", "value": "" }, { - "key": "2580a152668e225c064e8294c4ac37c0e2e937069585db11bcfaaacc739b0170", + "key": "47596d76736758786e7765427347684d5878ffff", "value": "" }, { - "key": "7bb100695dac90a27c6385d20132065a304982c5d526bb410943c77b01772bf3", + "key": "6e34667849774c6a496f7751777073765258ffff", "value": "" }, { - "key": "c376a2c6b5585e61f94d0dd49f836b6e091f05c716042b816d895803d35da8ff", + "key": "5341744a6c7a3076306b437a4733726a3538ffff", "value": "" }, { - "key": "685eb20b64a297b022101f367259d787fc6d3ef84daeade729cd71b64b57940f", + "key": "7531754c53597758535768724d7454326476ffff", "value": "" }, { - "key": "990762888677cd36590b778a873bc49872d1f2f6bec43eb3adff3b096af9fcf4", + "key": "626b3147706251616b6c56447335434b4241ffff", "value": "" }, { - "key": "81ee6f449452c4c3862725c94d2a913c81f7f1d1be7f7b45255214e6f8fcc34a", + "key": "69546b58587a587a6772634257434b424139ffff", "value": "" }, { - "key": "d1121ad88eb78aa120d5ca663a8b92b7a34f4c2e1472871e965372802b96cef7", + "key": "4c5135303537364244554b6746376d653642ffff", "value": "" }, { - "key": "f95291b046e3edd9e8b157034d6cabf7e150848c9e6c05304514ff2d71ca4b2c", + "key": "31564437704c327947347355364237527742ffff", "value": "" }, { - "key": "c556fb88c9ebdc24d01de6f3886ca66c7e3035e41cbac398cd45be4858135d23", + "key": "4e6d6a4d46524d573867484e644832704c59ffff", "value": "" }, { - "key": "ad474e1cbc6e139fae5b08d013c98f9c788ca2f5816acb1d89f31ac3d33180f6", + "key": "5154395a394d4c4b4d3969734b564a424866ffff", "value": "" }, { - "key": "f57b12b550d86c56b4deaed234856df8dff1198cc2cea6cb810e6d0ffccf1000", + "key": "594c4c314f6243506b45527662336b6f5945ffff", "value": "" }, { - "key": "116a37692d12c0f63e51bc31c9a28f19f35e908beb6c73fdc988c030375cfae4", + "key": "6957676b7639496d746d364f715576434b53ffff", "value": "" }, { - "key": "8aff23862f54a1b1389cbdd8bba222b3eaefb839aacd862f0e23a5c90dc80b04", + "key": "3052356344343357363556444c5850426a66ffff", "value": "" }, { - "key": "ea8f2dbf774b02bdf8401f778b5e4b814afb6ff48819f4e7a656f8cc46c282b4", + "key": "4f436f42716175787275626179306d4e5836ffff", "value": "" }, { - "key": "e80dafcaea120e1002d666d4241e53105949d9137d80ac63e962a831ac4f3cf9", + "key": "676f696b7246473575634578394d364f3167ffff", "value": "" }, { - "key": "81d2838e71f2d2a1c5fc13d0f0702f19afdb0ac1e90ed5a03b81f2dd34003992", + "key": "464875766671595934376845394b74524b78ffff", "value": "" }, { - "key": "6e9749e7f0d819136a79c684245a991a0d312cf2052a33b5ad590679794597db", + "key": "6d6f79535555704c30584657727053717964ffff", "value": "" }, { - "key": "eb2bce9b290497f29cd3ab28d8887127d1a3850c5194573ea126e69f538438fd", + "key": "724f674445656d75583072487a53384e7359ffff", "value": "" } ], - "proof": "22e0600a84011281010a20000da5e41c5fdd943b480cc680a1942d6708140827650e8e551df7b761bf56791a5d0a20002c041fe1df37d806cc5b493bed02222d83b25ffebf9cb529b4524cc547fbeb121e76616c75655f666f725f636c536e4d46714a4e6162776a7a5134356e6d4d1a07080118012a01002210000102020102030405060708090a0b0c0a7f127d0a20ffffedc8e4ee7f13c9892bf6277cdd60e4e8fad77abb37ca4f3b888a63b60df412590a20fffa9eb3a5e49b7261d86e27c0e1c17f39215887308f5e3ca48e3264b03d2a2f121e76616c75655f666f725f6b63395874466e5a4645784d416f4b6f37566c5a1a07080118012a0100220c0d020e0f10111213141516170adb0112d8010a202580a152668e225c064e8294c4ac37c0e2e937069585db11bcfaaacc739b0170125a0a20257d88a052b5f671ee07719f369d3a287d27eb02aa41f2ae717c3470fddcb402121e76616c75655f666f725f6c664e6743464d6c55755443486c5873474d69501a07080118012a0100220d1819021a1b1c1d1e1f20210b0c1a580a202586aa84635b02a6fd9bfd4a645da735891063bbe4735e14a7b937e8308e802e121e76616c75655f666f725f41704f486c45776c50666d6c59565744676437541a07080118012a0100220b2223241c1d1e1f20210b0c0ad60112d3010a207bb100695dac90a27c6385d20132065a304982c5d526bb410943c77b01772bf312560a207b2c032a70a46c912987028dfc8ed989a4f5f5eae1c2626dac69d5d5a607bfc6121e76616c75655f666f725f516f4d41746337385453764c376a4845627630731a07080118012a0100220925262728292a2b2c0c1a570a207bb9257d961f9ea70a91101dd30f96c296226909d31a1b2fb883b002571cd72a121e76616c75655f666f725f394f76546a5573534844734550456d794f3838541a07080118012a0100220a2d2e262728292a2b2c0c0add0112da010a20c376a2c6b5585e61f94d0dd49f836b6e091f05c716042b816d895803d35da8ff125c0a20c35ebaa6d60ec870e48ef65bf2c632ab3d6ac414eb8cef78d4d1af868bc5c1b1121e76616c75655f666f725f443049745348644e4f6435304448566a336d63411a07080118012a0100220f2f02020230313233343536373816171a580a20c37b78696b8c32f1487c15de1bb4941e344f675d7b74b96d2279d2eee6fd8282121e76616c75655f666f725f6f4b32455030396f696a4e585a544e52514a74511a07080118012a0100220b39313233343536373816170adf0112dc010a20685eb20b64a297b022101f367259d787fc6d3ef84daeade729cd71b64b57940f12590a20681557866f464b09f95217deb2a0b9f2da071a3b63e79afc9fb6198d42440939121e76616c75655f666f725f514256456f334771573473697271626368317a5a1a07080118012a0100220c3a01013b3c3d3e3f402b2c0c1a5d0a206888307ec39b834c9597df4005f6b40c6eb3f811810189f98bd6e2f0be8664b5121e76616c75655f666f725f335332696a5a7556314f553159514d4b624836371a07080118012a0100221041010102424344453c3d3e3f402b2c0c0adf0112dc010a20990762888677cd36590b778a873bc49872d1f2f6bec43eb3adff3b096af9fcf4125f0a2098e3e89d1a8514d914757bb7baf58f904e1e377a0d47297d61361a3f208b5377121e76616c75655f666f725f324975527a584e4b46435349324d49457278444e1a07080118012a01002212460202020101014748494a4b4c4d4e4f50171a570a20993543603fa16a93bdd509eb39c746e17b3c05b09ed3b64ff8c78c263eb132e7121e76616c75655f666f725f336a7053783870474d317131534950474f4e496c1a07080118012a0100220a5152534b4c4d4e4f50170adb0112d8010a2081ee6f449452c4c3862725c94d2a913c81f7f1d1be7f7b45255214e6f8fcc34a12590a2081e1fd2fb133c8f844b89a3c65b65dd7d3431304cb2029edb60e797bce18e47b121e76616c75655f666f725f4b7534384848673743474f49686664646a6553581a07080118012a0100220c5455565758595a5b5c4f50171a590a2081fc9839a5d72f3811399f731c8e428712a378f38a218504513dae48d3de6c6d121e76616c75655f666f725f424358687767576e374a65734b7a6c706c4c42421a07080118012a0100220c5d55565758595a5b5c4f50170ad90112d6010a20d1121ad88eb78aa120d5ca663a8b92b7a34f4c2e1472871e965372802b96cef712570a20d10a4c2bc235926e7d2968877c17fd0467cc6e67c5b2c099d45c21027ebe70d1121e76616c75655f666f725f57454c70656b49654673316b4c616f75646572341a07080118012a0100220a5e5f60616263643816171a590a20d1479a9dea95b41d19c215b5773b689d3954c650bc23c9de10fff616c28fb8ba121e76616c75655f666f725f537159466d6456424353586864747332554374371a07080118012a0100220c6566675f60616263643816170ade0112db010a20f95291b046e3edd9e8b157034d6cabf7e150848c9e6c05304514ff2d71ca4b2c125c0a20f943f4c68c88ae09b332a76425bc0da1d53a70a9ad9b7760f5651c8061ae860a121e76616c75655f666f725f42514268305a373267386e6f6a33684161376b551a07080118012a0100220f6801010169026a6b6c6d13141516171a590a20f969519028597e8729814d329b8ee4c64d24b5607eb31a4c6635da5e7858d0fe121e76616c75655f666f725f5a336e767a524763575a755343433337766e37741a07080118012a0100220c6e6f026a6b6c6d13141516170ae20112df010a20c556fb88c9ebdc24d01de6f3886ca66c7e3035e41cbac398cd45be4858135d23125f0a20c539755dcb7ec5e1e1d82ce2fb2212de46ca7b1fe737dcf2a8d6d3289bbc4ae2121e76616c75655f666f725f46796b4f4947794c324858514e7564436d7a64751a07080118012a010022127001710101020272017374757636373816171a5a0a20c5906d4a8ffbd182cf176a3c9cda00ba86e2a897a811da9db5fd6dd6ac4a7f1a121e76616c75655f666f725f4c386c597650653343495a5850795378347742651a07080118012a0100220d770278797a74757636373816170ae90112e6010a20ad474e1cbc6e139fae5b08d013c98f9c788ca2f5816acb1d89f31ac3d33180f612610a20ad43956581bb53f5b800c23dce36827aec61fc8d9a365c4aa76a805f7b87f19b121e76616c75655f666f725f3665793451614e70465257686f536857434638351a07080118012a010022147b01017c7d027e7f8001810182018301840150171a5f0a20ad5dbc2b233ea6c3a89d822a1e6ad058ea600033a2f3a21409100e1439bd0021121e76616c75655f666f725f6572596b334c6769664a4f57625164374159726c1a07080118012a0100221285017d027e7f8001810182018301840150170ae20112df010a20f57b12b550d86c56b4deaed234856df8dff1198cc2cea6cb810e6d0ffccf1000125c0a20f579ad5e63b2aca7b4bccc38d4b9c898b527e5afca7cf173e6bbd37132742ce2121e76616c75655f666f725f35456b71304b5735714e36354c6d7435487737491a07080118012a0100220f8601018701880189018a01141516171a5d0a20f6149f6a0cef987e8f199242ec188118f466d8fb4e0ffec09f01d4cb9f74ac69121e76616c75655f666f725f6164574972434771563431584870586d696741581a07080118012a010022108b018c018d018e0189018a01141516170aeb0112e8010a20116a37692d12c0f63e51bc31c9a28f19f35e908beb6c73fdc988c030375cfae412620a2010afae10cb45e26a4ff4fe5ed2625de6b8171f00acef0a473fab915a2dd84f77121e76616c75655f666f725f324a69467553376255364f56343448423558524d1a07080118012a010022158f01019001019101920193019401950196010a0b0c1a600a2011a28bd9aaed0166c6e9de5229bd7eaf0a1621fd1a86536e28aed2ce3c31b465121e76616c75655f666f725f376834676464386433646a5435306a4d4f5337691a07080118012a01002213970102980102990193019401950196010a0b0c0ae80112e5010a208aff23862f54a1b1389cbdd8bba222b3eaefb839aacd862f0e23a5c90dc80b04125f0a208aea038c3c1f56c5025d4182c2b4d4f836bef3d0ee155cfddbfe004ed61903ea121e76616c75655f666f725f666634634357546a67437a654f67546e765275741a07080118012a010022129a019b019c019d019e019f01a0015c4f50171a600a208b4ee3b5d19a4cc2805f4f68bf08acd0a12ce5d545fe506edd3e1fc014972f5b121e76616c75655f666f725f46665549363845687639674c51553850467761691a07080118012a01002213a101a20102a301a4019e019f01a0015c4f50170ae70112e4010a20ea8f2dbf774b02bdf8401f778b5e4b814afb6ff48819f4e7a656f8cc46c282b412620a20ea5a4ff69887238f1a2bd469ed6bd1366709a052a43f3c29c68609b3415dcd92121e76616c75655f666f725f4f6c31483132613334593051426d3654305049581a07080118012a01002215a5010201a601a701a801a901aa01ab01ac011516171a5c0a20eadab42ea68ad2a847112884cd39e1f4c8ce2968f8ba00ddb5ff866c1613f9d9121e76616c75655f666f725f666a794f71705976756c774247776e7044734d4d1a07080118012a0100220fad01a801a901aa01ab01ac011516170ae70112e4010a20e80dafcaea120e1002d666d4241e53105949d9137d80ac63e962a831ac4f3cf912600a20e7fca8dbbceac9c969b98cc35a2225c70d3a7587c7b1758c60d79bec603217a6121e76616c75655f666f725f625755566e6438414a37524c6e397a62794f4b551a07080118012a01002213ae01af01b001b101b201b301b401ac011516171a5e0a20e83b9516c1667a669b72245f90800570cc35f69eb24afdc4adc038f80d97fdba121e76616c75655f666f725f5a61536b5339414d375a74446c773347473775361a07080118012a01002211b501b601b701b801aa01ab01ac011516170adf0112dc010a2081d2838e71f2d2a1c5fc13d0f0702f19afdb0ac1e90ed5a03b81f2dd34003992125d0a2081c49917599f2a0f69e96abff5cf3bc788dff54ccf13024a910b062d594f2517121e76616c75655f666f725f424f32476a67513549544565697530686a4675461a07080118012a01002210b9010101ba01565758595a5b5c4f50171a590a2081e1fd2fb133c8f844b89a3c65b65dd7d3431304cb2029edb60e797bce18e47b121e76616c75655f666f725f4b7534384848673743474f49686664646a6553581a07080118012a0100220c5455565758595a5b5c4f50170ae50112e2010a206e9749e7f0d819136a79c684245a991a0d312cf2052a33b5ad590679794597db12600a206e3d9be1203153c9f9800d3a59b643070303a8eff375fc446d40a0bb4aff025c121e76616c75655f666f725f42655937654e5442385a4a4572474c45346132341a07080118012a01002213bb0102bc0101bd01be01bf01c0013f402b2c0c1a5c0a206ea196ac35de1b8866853a28b8c3e961eb15d7c4fc624ebcd1ee5d31144a196a121e76616c75655f666f725f57726b7036354c654934787268506270744776541a07080118012a0100220fc101c201be01bf01c0013f402b2c0c0aec0112e9010a20eb2bce9b290497f29cd3ab28d8887127d1a3850c5194573ea126e69f538438fd125c0a20eadab42ea68ad2a847112884cd39e1f4c8ce2968f8ba00ddb5ff866c1613f9d9121e76616c75655f666f725f666a794f71705976756c774247776e7044734d4d1a07080118012a0100220fad01a801a901aa01ab01ac011516171a670a20eb3b19ad17f8a2567235d253276e827eb4d93edf9e487bede18260a0a6ffb77a121e76616c75655f666f725f7a48744a4d34333865764d526d515151673947371a07080118012a0100221ac3010202c401020202c501c601c701a901aa01ab01ac01151617122708011201011a204c27b74a03394f254117dc2dd4aaa27ad2a3eccb0fa6f23dfc52eea501d133cd122708011201011a200000000000000000000000000000000000000000000000000000000000000000122508011221010000000000000000000000000000000000000000000000000000000000000000122708011201011a207a9e6f4327be207f312a80fecec582699f45b35e7fd2c3357c9c5ff7432f36f6122708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad122708011201011a202267b5ddaf71187e34cc533c3e7ee25dfd386a3698249a482c28b4c4016389f1122708011201011a20d80dd2a33eba727f1464bc6ae82a164d56f057cbcfd68e8e5e01b16d62ca28f8122708011201011a2024f1a08038cec03788d6692c5f6581ab50318277ed47932e6d3bcf750df64141122708011201011a20050961036298f28b550ce8123f9f9ccfefcaf1059808c2f285bd24915da7ca80122708011201011a20657d93a7331d35712e8480057c06baf379c8a2aada48365bfc943cc7b36af94e122708011201011a20eaac481f8ac8418ee1eabde1459b6ff7369b5ce8c034d63fc0169d49f9827bb4122708011201011a20207bedb000df636941dfcd8393a399cca2f3eea7013beb04c8257e36aa11f03a122708011201011a20e49182ab61bee9b787132b4092c4b3014f170ee3e845786f362998a9122984e612250801122101b76263b0c4e8438e81f21cdbff1e21b894a3c0e4ea08a0deab7c1de3292cd16a122508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd1225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d31225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba1225080112210146eaec810967e45673028074c769ca2a8ddb3a5dbd47eab5cb6c5ccce3496eab122508011221013ff09e39daa0a77181976e045c441e4716144988ccf7cb308ef9820f4011143712250801122101ffdcb7da910966808d2d3bb3fd307b689c3ad49b9fde1424896c12063a84b75f12250801122101676d00d395acdcc0dec167c1a3ccf45fa415737faee5b74e8754df794a88b64d1225080112210105ed2c700945fe28a9fd7552975cd76e047454319f029bbf5be265c9bc54554b1225080112210154350e9d386d3ec494f76d0ce140dccb32a12fcf150745aab95471a2cee21fb1122508011221015a82302f68e12cbba17ccab8920ab5a100d9770a1504fe6b8d066beccd659745122508011221012d64758d6682c0d72a498d55be1ec1447b47cd6abf1d4ea8d4872c68dfdd11ef1225080112210116dc6e2093bc12c50a487ce251d8f1a5b3a1af59c3eb7132adbcba9f1fa778bb122508011221012dc2849158c9807287ecad05813a751ad863c4b7f66a243b66e991586bfccaf5122708011201011a20b6741f49d2db5052180ad02cca231c6aeac1333d515d6c490dac6e770278f638122508011221019a586bc3ee20b13fd03bf5b2a4461d5dd6fc5cf05c4c9c57303216e99dfbe239122708011201011a206dfada962670bb53945431e85063e191d5dc0fb6f19207d0a03d1055f801ad911225080112210119a4d2d17a37faf0605c8ac65cb4aac72de3d7779c64c8b78577df090685d442122708011201011a206db2b5ae7a1de14f4a8f779f0f12a4b67357945d3c15ecd7271aaf07a74e2dfa122708011201011a20d19a3c11a42b447b179bcfc7431a943cc3f597981a6c6dd91f994e1901e752d41225080112210118a3123f008e521520843625006577c5112f13fe624851e68a75613b7ac1a9e8122708011201011a2007b9aed070bfa3929d6dd5a4ab0d002c36e8a467f3d94e0d1b0d31773fd704d1122708011201011a207ec97d7e83fc505c030b81e395a5b19c1be86ed9f9dcd1fbb88e5edc5cbc6ad51225080112210168b051546044bfd33fc353d9a1b51b3afb762d3e27bfc475857f4295038e3254122708011201011a20eceb5dad8441fb687bf912c86ef77e3450902da06974913d4cb9881edd19a25212250801122101023ab1561db5979c5f009da8950a89b1b2c46bfe483bfda8d74d408a9564f04012250801122101ad0c58847b38b345ddd65b451ba0718df445572144eb2d5bab8225320a4d3869122708011201011a20a9672370788bd4c3b21487e1ff7daf9fd29055c33ef245e0d7ffbf29423afa0a122508011221017f42ba0ab9cf7c3328509a669ff3f005fff65768eda3c78a08b507aa291e9f6d12250801122101550e4a13c7e10998bd0f28e012103c375eb83d02f870868e199a7c32d741c9b012250801122101ad81a0c099cd1f93e449fa2f4aa848c28e34fb0e4abc32d88fa05507418592cd122508011221014fbe2d9c3066bf90ee87f5286b5adbe15b2b24ee71d39d1e975e24c964aef074122708011201011a200279a632ab7ad843f7aefc02c89d48423f765997719f2307177f9434e9f5845a122508011221010a5a5481f3a9523d353374777c2824c8487e4fad776105fb77d7fa2a11ab5732122508011221018015c60e22701c790051b93199dcd790c1733d79910898c85ced29e2ea03c464122708011201011a2046580f4438d7970a757449a1a8d7ab19b278ba7c5fd5041ed202dbfb62cfe66612250801122101e78070ad5b6a3392a54d1b7f541ee6ffc0a80b4f1dcd0286095a8f6330ef8fb2122708011201011a20cad792e7f4ee64cce5847de67882c26578efbd13700c7b032979c711e838445512250801122101f00585ec6dba7a13f34f71b9493a0d6fc5591638b51848d004702ccd4f697a50122508011221010efd2907c3aff8dafb0f72da84ceb19376fa1bec5d305c32101885b61aad5e7b122708011201011a20beb48a5b68c0fe3e514b4de894c96364087812a55e8dbb81a25a9976d91ea839122708011201011a207829c213824cc50a7705b799054a848decd28dd78183683ec6b3b57e1a207f5d122708011201011a20b0d25f9fe186304e97f7a1892ac21caa48deac5750adba83e8e7a3ab68ae294e122708011201011a2093fe012ca5775953d19f43e1e12752b88532608588f6b07b0cda97014579d37e12250801122101ad0e0a75d718ee8919e1ec2dd1b8ca45166f8868bdec7f52cd9a09aa2953a946122508011221019f6407dbbfd7317dbbda4d25ed767c45e897bc245a5051f2e7d9f1ccd9afbdfa122708011201011a207a147bea1ab0387504da2f907246d88cb8fd53ddb2cf994f9f7a86a053a18deb122708011201011a2001e07e7bf8b20cf9066b74cddee526edd36d760371a64bd11ba37339a4996b56122708011201011a20378eed6ef4ef986fd3d7ecc60b06fcb5bd991c51cc3b5fe7c2bb1ba5737f8ee4122708011201011a20ab1fbe82c840394b173785b166a6b40a71a3aedc24faed220c9d33d93501aec0122508011221018b014adefc2221a8fcda04c892040142485f69b15d85328789f94c9c6d65ce4c122708011201011a20d05bd5732fc00ecb341952f6f55240f00e795da842cdc333d3e21502620c6c03122708011201011a20cb5777a5c3853d79d3ba5a6a3bddab7d4bd3a18ef5e643742967b4b51a1f03cf122708011201011a20a6646e092d8a0fcaf26dc966b9b34987fc90bdcd5559a9182ce2671466b333b8122708011201011a20ddf7b89fbbae808f635f9f59f10fe3f29ebe2d9240158c7a0872bbfedcf02836122708011201011a206180367e0ef1e3eeb5b068ab5f27e59a581a516a40da40f4aebb8f6bd29923e912250801122101f28dcc2838635eddf2bc18727e1a0bbe6decb542a24c14f4732f793cc721b5a712250801122101c5b198042ebb553554734a4bfd8e11ff6682d7ee6638843153acce1d3666422f122508011221015074b5597289337449fd4e5198114ee3f8fd435204441bbd95ebc9ef1ba91874122508011221013182a16a4ab4e353d7e1c5f19e4bc32ddc94edc6ed22e1c82e28bf15733725a71225080112210115ea70cee62d2f5efdcb63881f3b493d1996f7ad61fed31af16f3d164229e481122708011201011a20d58a02ed02aa73394de38e275f99d8dd5ea5e71d5dd673bcb403e66b304294bf122708011201011a20c95ac9668a34761ccdd111d856992b20a0846b3e5e0e0a22121b752c591b7613122708011201011a203ae55f08905c68a2adbcdeacb26de2d609bd3e869ac66bac631e9502c92ae8f512250801122101fb082f2df8a2307274e40a7016cee71ade05e54f5558ed4f6c39991d4eb5c117122508011221018b7196f52f76efcbb7ab0467d1414a38bdc3301c978dbc5b326795d1bf431482122708011201011a20c4921f1afa5739d3a359f971e40a431a98b0188dd4b18f160ded84545769ba34122708011201011a20f8077d7c466da631d21ca54e1544db9ce6a2a4fd15145ec12fbc4adfc8e26628122708011201011a20d36e2a921c9f7e87f5b765185a991a4749ade4f99a6d5ac857f38665ae2ac3cc122708011201011a200ce4eb85cd6410e4c5e303948cae5a95522127b5a7fb491bf067f99e95ab6b6a12250801122101dbbc1bb871e574e1e708abf438782a09b4d4b6e8286c50a388e9ee5e4852b390122708011201011a2041e849a4259c8a305a7759e67a8e6fc95bb621a07a471ecfd3dacd9e353d824f122508011221012b5a98832c7bc5dd54801e7e100706332d58e560208fb62b06f3a77ddbecf075122508011221010ae70fac14ef0aa1b4051938569745fb3eb470675659b974f4bf68bf9706a7c012250801122101be4bf66cd45a4c4aaa7ff3857c3a42814555c7f7ec772bb1064dba946c6b328312250801122101eaf378c5c63442c551b21d5b6e43d54be67d451e2d26908afc2ea2cc3ffe3b7d122708011201011a20950e2179c815bfd8907d58128a7ae7c97daa5ab575af4171f644c8099010ad6f122708011201011a20d47d2c30c8448077ffa573c2c35a006220d7608a871e818ad29d3716daf485b9122708011201011a202b2520f45c94631a59b98227c7747a212e4fcb5e4d524464c84e67ae67e1c28e122708011201011a20d4a6e9e4496a7cd271b0e307292f254b38499c76ab01dc848331527e069b093b12250801122101168ddc9f9d7a14ab6353e9d31cb9b26fd91d2752bc8c5e7414d1e1cc4161e9fb122708011201011a200c9b1918cd04d1dc8de6b4fbb6a971f78bac178c5321f963df0b59606148cf5c122708011201011a2008bec402582cd245831ef538bb6dcfb9f3de2e7c8cd3e4077ea056998dc379591225080112210151dd9cb84f73eb1fba6f402ab9c79de2f5e4808612f3a209764790c661c8328d122708011201011a201e1efde4d1f12bbfceef37c9d9ffb43116624975f0a9a28ca642d9c500a7c8c0122708011201011a206e668cd3ff566cbbebdc256e9fe214a381079b6b9f4377909b76cceab49952f6122708011201011a203978d57f079ea09d6d6d32710f019c4b09315375ed3ce1173e0667becb564c93122508011221011aeb41adebc824fb9df4b0f004133ea0068f8d6048dcb3435af8d7e803710dd4122708011201011a20bbaf5df03403cb51ddf9090316fd0d0ed1077412394f7a2861b5da7d8bc98ebf122708011201011a2043d773c45158fdb231c1ea4ebd2ec61457fa77a886abea1981a6de4d263d4e8b12250801122101265936384fa658c0148f1842b942b9a2b5ff05f91edba9b997984aa9780cb3821225080112210157204e13cd8146b61b0864d4ec1fb2926bc4207ce3729b716f225b346edef077122708011201011a204aa1b82cd090ce99c3666f16b801cf28efa0e1dacdd91b46348aaa36117ae997122708011201011a20932fa47c2c8611b852545d85a3714e5b84102a1817b3d32ea359fee69376fcc0122508011221014a7fb59a20c67de5c95d701741dcafb0b2b424587d95ba08a48ea2887cc0be9c122708011201011a20ded91efa4177fffdac2795e86b73c57c25b6e5e77d390c3877859b791f385811122708011201011a20a3ed532793078461e21b64376577f3789338ec5bab6cc6559aeb306e7f9e3242122708011201011a207169495e53d639cb5f13e370c122e8266a3430217295336f77b592dd39bfa701122508011221011a5daddc81b3d7410433820681e37ab2437f978703ca2775f844a2992cd5595d1225080112210109e6a3c6b1dbc32d1af5178a7baa3df1e31ccf8520255a4aca37e649d62fa3c612250801122101001dd12ced870d2db0527fcd98cfb45f1c04a8211ab7292374010b6b8f0c01d812250801122101e2579b69672d24b2c8ace967126eb5c293ef978e3938ea2d94eed4f5dbae70b3122708011201011a20e98e3bc7a05844a192e2a9361f277188aab93853abdf34419ddd7098c090d8f51225080112210184c49247fdc0aef20e8dfaf047010764e084c4ae6b8a449eaebd1a6927c1bc63122708011201011a205431165031aa3557730f1f05b3dc36c981a29816f4851814838017203f34627a12250801122101983b2afefe44d668c42a75d72a4b1a06facc2dc38610acef33a7438fa918a98b122708011201011a20eb3e05749d936ecf8b5c5a09c52b9b58a8895be01c96bad625bdb7cc5135693e122708011201011a206c3c861f0d62e4945af0703f988a1c8571c1fbbdaee993f8d8114642374952ea122708011201011a2021e74bfc0537e1797d39980b1199b995c02a3d00dd4e7a84e72dbe8bc5aaf1d11225080112210137bef4dd27c2de86a41e7d487c2948ac12513bc72e3412ede04ca8526d102620122508011221010d1c82784b297bc946c7374232bdd741b26c73254271bc1d76c9e5e15e639ff6122708011201011a20579bf4a18e5abe8afdae625fd7bb4a4f341079bb104e1885fb322bd003c570a4122708011201011a20ae1285d65eb55c18dea08d4f2ef0a28791036650049025ec07fe0697c0a35cfc122708011201011a207a249163982a35cb260955598c1b1f143ff4bbb2fca0464f39315bc57012023a12250801122101dbfdb2c64bddc6cfd01e6f3c0ddfd36b13de2fc4315bc269901623bfff6027a1122708011201011a2081ca61864da86da04206d60b2939fba9a6ad4bb870eef466817b0e30c24c00471225080112210187642824cab7c3bca0044843945dcd350c5a61c7906792127d671f48de5d74b612250801122101e4feb818b7962b4c285c88154e13c8f6abe76d423ac20625d203a0405515cde4122708011201011a20925fb91059591774f00c6811e744444d43a09871a3be861325a404e0e1c406bf12250801122101ced5a0edfbcbb8e31f8bb407ee4b0adb3589d4212526f21fa96902a6cca63e39122508011221014c577d59f564ec54507d8161e5b79d5a411f2c4b1ddf46610d8b5c85c77c0abf12250801122101ce89e96deed4edb3294ee79b61ef950658df0430643d7f8315f39328d782dc9f1225080112210153783e42e17fc0eb36a3f982a3fc1ddac5481ce0f32dc9c2ccef4242044c03cb122708011201011a202b71ecd92886968bec1e3fed4e38fc54970c5007afa577c986316ba7635e355b1225080112210145200a18f2534749cbae17b829c2017b9c5609f480f091174df38f22416796c0122708011201011a2025f9d3d32e3ef8611589c63760b1a0e529028e17fbb1d557f8d753744dd56a8a122708011201011a206cb1efe64f6a744a6df7eae9b5e4f3f6c8eace5fd8e62e39ca2efa55cdbd7716122708011201011a20d978e2a4250873127c9f23c6424683557785624be9d66ccd62fa3404c4a743ec122708011201011a20f454e11d5c5030462b435f2677d7514c96629d4cf97b6a7e7c6a0cd894e3bba912250801122101124e9eb2c6a0ec7f465527caf0d9f3bfbd26568d78f5dcaafac599ce22d59eef12250801122101e7fa82c24f93c1690f3e564b0a3f1b45eaed3c8f06bdcbc59a1fa416d7d5c820122508011221019efbbbf59c7ed77a5d3dc61b8b6f77178c2a2ed3ba6dc7fa61fffde02d19d3ee1225080112210185e5a25bf7906404130d2b57db9e68d8192919cf0ff186e694b1b019fd58ac88122708011201011a20388c501b4bda0c64c0a85d74d9ad1e7608de52b067a5d893ad83042aa0ffe5ad122708011201011a207b652e83c4d49c7f9476079ebde01742b61f724d51b8550d44ad2fa16e7d1044122708011201011a20879c5704e1df82bba5645ab26fce2d587d5a6f02079d0f43c349e9a4535672b8122708011201011a203ad0761e4792bc789662828ab3983b31f4a93acec2f90306139bf8f85269a30912250801122101afa7971e8ac0609e2709ae13f218c83c632264c318291b2327c1e163305be47b122708011201011a207a4bce1ca4d1704903682e21f34eee82624907005e9ddd04b9fb084a87ba90d4122708011201011a20fa1881d8ea106faf335443cf0d5d84527c9dd421261a90b47ef3329bd9e843021225080112210189ac47f9679cb5136d295b78135c584eedad4123f92fcc94a64042e6823b0d6d12250801122101b6932938bdc08d6c13168390915b0b25d3c1d7951f3c61fc1c8fa49aa83cd4cc12250801122101d1995a2c320859d1bd9aa030124ab0517efe6944199877d95e46f6f964b5675612250801122101f881a68647ce50b69bf6be83bae146818eff71f878fa8c4c029c55b5b74dd9a3122708011201011a2054d77251f3b9f9c182a697d6f7edb95df5c43b38fed17c1974de6173efd979b412250801122101881c6394330f1602650a5226eac69263760f6303c6fe57088eae4b7d2809c0fa122708011201011a2009584133a128b5cdd27d1902cd73bb26ba479f1465a45990745e1bfe1c0b364f12250801122101bd64f703ec247f0d05a2877cba5fd9054f906c77fc3c00748f9c70a293a69fa6122708011201011a2077171562898b61be985cac22245826cd3799c3f0d9e0c09b7bb189e507c9edc5122708011201011a2016755dc9c634c80daf33278047ecbb82c8c542f71f144df20174128a3c904b76122708011201011a20eec0fe7410e008660595e66453704a4b2cad1cbb0a2420587b671bcaad1a8fc412250801122101414e30f086e99fd26c84b8fc04a4e1c38c49391eb921a588b3da49266a4a81f7122508011221011218b892bcd51b07b3b3850a448137ae28d1069d52bfbdb4a089c63fd40c368e1225080112210133568cec91245ccfd99f706c0563da48ce20cbadd2b51e1321ca54d045a9eb69122708011201011a20387d3570b66fa4e33a67e0f9d1fae695ab443a2f390e85b33a9427e546a8aec5122708011201011a2072c11303abe2de4843f725e40b00c9a2dff73ad8d4154521023ed8c8739ff68d12250801122101fdbceb97af12f8a1b83c3b759c1fc825e88c6090dc0d6b9caea961f68dc72c87122708011201011a20d3ed620e0d585ba618305f599988e15462ec48a24f3ec7ce2a00dddbdab7d09312250801122101668e2886cb8f73ae5295f09f20c316c21d7e633be2dae7b5a01b7c01d2830634122708011201011a20cc864565c845b4b53f083f69dec68438cd7ec8b848d485ffb6e893fe23f7e9481225080112210164ee33c6aa4304be656d80def8076791f2dbc6b54dc0fa997b0a9115747946bc1225080112210177556c07ad032fd183a1978441759260a29024cad7bf3740a5ee6cdd430ce91b122508011221017c057e865671e80b6dcda27d853772a1dff6fb41a6faac19af955678c77777b0122508011221015703835cdc085a48af6a648f43cf8420e4c81b503bd027c04211ef214b16172612250801122101315cd538f57e740ae25dc64464e6d7e1046a8c0777d9bec2e43886fa93e806a91225080112210124658892b5eb1979411d9bd12c643c70ccc1b336019df99471052dbca80aadd61225080112210142da6f06c33256fe77868c5812f6670713cae0b316425a77095a4b6166144e11122708011201011a20912a404f9b2dc0f3f92bec59ce1c9fb4c996a7170ada989eed88ce99628d17b8122708011201011a20d4eb294bdcea1065c8b24d57b4d1cd26b78f5345876907eda5eadb3e3976711c122708011201011a20160954659cb302bdd5cdafba68e113d9722394d9123a9cad87d7f128b0ce82c8122708011201011a20dd3fb99172a19ad6216c1c37aa45454d1803edf2f8e7dad77183928e017d9b8d122708011201011a2094650fcc185f666d229c717f56d44c0f40e96edc97dc22241c12178bac1b7c2812250801122101081c87cf7e23e1684a1886c0b22632f781bfde116fe2532e9256745f387811fe122708011201011a20fa6fa443a12c046fde4c437512f93fa6298ef6caeb1a99a01ed4ec062e5c2cfb12250801122101027b83e2628c39fb8340f33201a369fd6829ab6bf8e377bcde10412edbe5d9cd122508011221014f7ff1a0ef376fc76fe17953326045fc55d15e0042bd2160a8ebe01707d5a010122708011201011a201bf04c90368e4d72789b28f7b92bd582ce1a57a0f7cca50354511301fc360954122708011201011a20cb212bf4e11cd0a802dac501b71e877a669972f5d5e42c872ca9a7212ce79f25122508011221010b0dd000cbdfaa449f6356d4c710f88fece010774a9cc37dc656006b6c57577e12250801122101d60ca8a578c0ff7c0ca1024e5f66384ba4b8d85b6eda74f9464a43802e099391122708011201011a20d48ecb49a8205bf745d2963dd049a18b1db6ecbb20804d3b082c35f223b45f1412250801122101781d8d6f9695c35e68f320e3c2c07daf4c2fcfc5424527eba12aaf3a5dee8cc1122708011201011a206a6a5ce23cfb2174b88722a33bebc75e6b19ddc2391b973765032589793e32e0122708011201011a208894e9af93c88db14468a9c521af8e9894dd83079685a9f5d7a96ed4354d736a122708011201011a20e130943aa2036bb38beb3a5a8c0adf3530e8faa8aa592631fab0bcdd4bdf3472122708011201011a2012e560a1834e04950797d61ad16ddca9afc18c7979b5b9334608d04dcd870c69122508011221013be828dff60654f87ea63d50ff15c8549c2f92f8091cdaf0c579c24e00dde22c", + "proof": "22e25d0a7912770a20000da5e41c5fdd943b480cc680a1942d6708140827650e8e551df7b761bf56791a530a14636c536e4d46714a4e6162776a7a5134356e6d4d121e76616c75655f666f725f636c536e4d46714a4e6162776a7a5134356e6d4d1a090801100118012a01002210000102020102030405060708090a0b0c0a7512730a20ffffedc8e4ee7f13c9892bf6277cdd60e4e8fad77abb37ca4f3b888a63b60df4124f0a146b63395874466e5a4645784d416f4b6f37566c5a121e76616c75655f666f725f6b63395874466e5a4645784d416f4b6f37566c5a1a090801100118012a0100220c0d020e0f10111213141516170ac70112c4010a202580a152668e225c064e8294c4ac37c0e2e937069585db11bcfaaacc739b017012500a146c664e6743464d6c55755443486c5873474d6950121e76616c75655f666f725f6c664e6743464d6c55755443486c5873474d69501a090801100118012a0100220d1819021a1b1c1d1e1f20210b0c1a4e0a1441704f486c45776c50666d6c5956574467643754121e76616c75655f666f725f41704f486c45776c50666d6c59565744676437541a090801100118012a0100220b2223241c1d1e1f20210b0c0ac20112bf010a207bb100695dac90a27c6385d20132065a304982c5d526bb410943c77b01772bf3124c0a14516f4d41746337385453764c376a484562763073121e76616c75655f666f725f516f4d41746337385453764c376a4845627630731a090801100118012a0100220925262728292a2b2c0c1a4d0a14394f76546a5573534844734550456d794f383854121e76616c75655f666f725f394f76546a5573534844734550456d794f3838541a090801100118012a0100220a2d2e262728292a2b2c0c0ac90112c6010a20c376a2c6b5585e61f94d0dd49f836b6e091f05c716042b816d895803d35da8ff12520a14443049745348644e4f6435304448566a336d6341121e76616c75655f666f725f443049745348644e4f6435304448566a336d63411a090801100118012a0100220f2f02020230313233343536373816171a4e0a146f4b32455030396f696a4e585a544e52514a7451121e76616c75655f666f725f6f4b32455030396f696a4e585a544e52514a74511a090801100118012a0100220b39313233343536373816170acb0112c8010a20685eb20b64a297b022101f367259d787fc6d3ef84daeade729cd71b64b57940f124f0a14514256456f334771573473697271626368317a5a121e76616c75655f666f725f514256456f334771573473697271626368317a5a1a090801100118012a0100220c3a01013b3c3d3e3f402b2c0c1a530a14335332696a5a7556314f553159514d4b62483637121e76616c75655f666f725f335332696a5a7556314f553159514d4b624836371a090801100118012a0100221041010102424344453c3d3e3f402b2c0c0acb0112c8010a20990762888677cd36590b778a873bc49872d1f2f6bec43eb3adff3b096af9fcf412550a14324975527a584e4b46435349324d49457278444e121e76616c75655f666f725f324975527a584e4b46435349324d49457278444e1a090801100118012a01002212460202020101014748494a4b4c4d4e4f50171a4d0a14336a7053783870474d317131534950474f4e496c121e76616c75655f666f725f336a7053783870474d317131534950474f4e496c1a090801100118012a0100220a5152534b4c4d4e4f50170ac70112c4010a2081ee6f449452c4c3862725c94d2a913c81f7f1d1be7f7b45255214e6f8fcc34a124f0a144b7534384848673743474f49686664646a655358121e76616c75655f666f725f4b7534384848673743474f49686664646a6553581a090801100118012a0100220c5455565758595a5b5c4f50171a4f0a14424358687767576e374a65734b7a6c706c4c4242121e76616c75655f666f725f424358687767576e374a65734b7a6c706c4c42421a090801100118012a0100220c5d55565758595a5b5c4f50170ac50112c2010a20d1121ad88eb78aa120d5ca663a8b92b7a34f4c2e1472871e965372802b96cef7124d0a1457454c70656b49654673316b4c616f7564657234121e76616c75655f666f725f57454c70656b49654673316b4c616f75646572341a090801100118012a0100220a5e5f60616263643816171a4f0a14537159466d645642435358686474733255437437121e76616c75655f666f725f537159466d6456424353586864747332554374371a090801100118012a0100220c6566675f60616263643816170aca0112c7010a20f95291b046e3edd9e8b157034d6cabf7e150848c9e6c05304514ff2d71ca4b2c12520a1442514268305a373267386e6f6a33684161376b55121e76616c75655f666f725f42514268305a373267386e6f6a33684161376b551a090801100118012a0100220f6801010169026a6b6c6d13141516171a4f0a145a336e767a524763575a755343433337766e3774121e76616c75655f666f725f5a336e767a524763575a755343433337766e37741a090801100118012a0100220c6e6f026a6b6c6d13141516170ace0112cb010a20c556fb88c9ebdc24d01de6f3886ca66c7e3035e41cbac398cd45be4858135d2312550a1446796b4f4947794c324858514e7564436d7a6475121e76616c75655f666f725f46796b4f4947794c324858514e7564436d7a64751a090801100118012a010022127001710101020272017374757636373816171a500a144c386c597650653343495a585079537834774265121e76616c75655f666f725f4c386c597650653343495a5850795378347742651a090801100118012a0100220d770278797a74757636373816170ad50112d2010a20ad474e1cbc6e139fae5b08d013c98f9c788ca2f5816acb1d89f31ac3d33180f612570a143665793451614e70465257686f53685743463835121e76616c75655f666f725f3665793451614e70465257686f536857434638351a090801100118012a010022147b01017c7d027e7f8001810182018301840150171a550a146572596b334c6769664a4f57625164374159726c121e76616c75655f666f725f6572596b334c6769664a4f57625164374159726c1a090801100118012a0100221285017d027e7f8001810182018301840150170ace0112cb010a20f57b12b550d86c56b4deaed234856df8dff1198cc2cea6cb810e6d0ffccf100012520a1435456b71304b5735714e36354c6d743548773749121e76616c75655f666f725f35456b71304b5735714e36354c6d7435487737491a090801100118012a0100220f8601018701880189018a01141516171a530a146164574972434771563431584870586d69674158121e76616c75655f666f725f6164574972434771563431584870586d696741581a090801100118012a010022108b018c018d018e0189018a01141516170ad70112d4010a20116a37692d12c0f63e51bc31c9a28f19f35e908beb6c73fdc988c030375cfae412580a14324a69467553376255364f56343448423558524d121e76616c75655f666f725f324a69467553376255364f56343448423558524d1a090801100118012a010022158f01019001019101920193019401950196010a0b0c1a560a14376834676464386433646a5435306a4d4f533769121e76616c75655f666f725f376834676464386433646a5435306a4d4f5337691a090801100118012a01002213970102980102990193019401950196010a0b0c0ad40112d1010a208aff23862f54a1b1389cbdd8bba222b3eaefb839aacd862f0e23a5c90dc80b0412550a14666634634357546a67437a654f67546e76527574121e76616c75655f666f725f666634634357546a67437a654f67546e765275741a090801100118012a010022129a019b019c019d019e019f01a0015c4f50171a560a1446665549363845687639674c5155385046776169121e76616c75655f666f725f46665549363845687639674c51553850467761691a090801100118012a01002213a101a20102a301a4019e019f01a0015c4f50170ad30112d0010a20ea8f2dbf774b02bdf8401f778b5e4b814afb6ff48819f4e7a656f8cc46c282b412580a144f6c31483132613334593051426d365430504958121e76616c75655f666f725f4f6c31483132613334593051426d3654305049581a090801100118012a01002215a5010201a601a701a801a901aa01ab01ac011516171a520a14666a794f71705976756c774247776e7044734d4d121e76616c75655f666f725f666a794f71705976756c774247776e7044734d4d1a090801100118012a0100220fad01a801a901aa01ab01ac011516170ad30112d0010a20e80dafcaea120e1002d666d4241e53105949d9137d80ac63e962a831ac4f3cf912560a14625755566e6438414a37524c6e397a62794f4b55121e76616c75655f666f725f625755566e6438414a37524c6e397a62794f4b551a090801100118012a01002213ae01af01b001b101b201b301b401ac011516171a540a145a61536b5339414d375a74446c77334747377536121e76616c75655f666f725f5a61536b5339414d375a74446c773347473775361a090801100118012a01002211b501b601b701b801aa01ab01ac011516170acb0112c8010a2081d2838e71f2d2a1c5fc13d0f0702f19afdb0ac1e90ed5a03b81f2dd3400399212530a14424f32476a67513549544565697530686a467546121e76616c75655f666f725f424f32476a67513549544565697530686a4675461a090801100118012a01002210b9010101ba01565758595a5b5c4f50171a4f0a144b7534384848673743474f49686664646a655358121e76616c75655f666f725f4b7534384848673743474f49686664646a6553581a090801100118012a0100220c5455565758595a5b5c4f50170ad10112ce010a206e9749e7f0d819136a79c684245a991a0d312cf2052a33b5ad590679794597db12560a1442655937654e5442385a4a4572474c4534613234121e76616c75655f666f725f42655937654e5442385a4a4572474c45346132341a090801100118012a01002213bb0102bc0101bd01be01bf01c0013f402b2c0c1a520a1457726b7036354c65493478726850627074477654121e76616c75655f666f725f57726b7036354c654934787268506270744776541a090801100118012a0100220fc101c201be01bf01c0013f402b2c0c0ad80112d5010a20eb2bce9b290497f29cd3ab28d8887127d1a3850c5194573ea126e69f538438fd12520a14666a794f71705976756c774247776e7044734d4d121e76616c75655f666f725f666a794f71705976756c774247776e7044734d4d1a090801100118012a0100220fad01a801a901aa01ab01ac011516171a5d0a147a48744a4d34333865764d526d51515167394737121e76616c75655f666f725f7a48744a4d34333865764d526d515151673947371a090801100118012a0100221ac3010202c401020202c501c601c701a901aa01ab01ac01151617122708011201011a204c27b74a03394f254117dc2dd4aaa27ad2a3eccb0fa6f23dfc52eea501d133cd122708011201011a200000000000000000000000000000000000000000000000000000000000000000122508011221010000000000000000000000000000000000000000000000000000000000000000122708011201011a207a9e6f4327be207f312a80fecec582699f45b35e7fd2c3357c9c5ff7432f36f6122708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad122708011201011a202267b5ddaf71187e34cc533c3e7ee25dfd386a3698249a482c28b4c4016389f1122708011201011a20d80dd2a33eba727f1464bc6ae82a164d56f057cbcfd68e8e5e01b16d62ca28f8122708011201011a2024f1a08038cec03788d6692c5f6581ab50318277ed47932e6d3bcf750df64141122708011201011a20050961036298f28b550ce8123f9f9ccfefcaf1059808c2f285bd24915da7ca80122708011201011a20657d93a7331d35712e8480057c06baf379c8a2aada48365bfc943cc7b36af94e122708011201011a20eaac481f8ac8418ee1eabde1459b6ff7369b5ce8c034d63fc0169d49f9827bb4122708011201011a20207bedb000df636941dfcd8393a399cca2f3eea7013beb04c8257e36aa11f03a122708011201011a20e49182ab61bee9b787132b4092c4b3014f170ee3e845786f362998a9122984e612250801122101b76263b0c4e8438e81f21cdbff1e21b894a3c0e4ea08a0deab7c1de3292cd16a122508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd1225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d31225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba1225080112210146eaec810967e45673028074c769ca2a8ddb3a5dbd47eab5cb6c5ccce3496eab122508011221013ff09e39daa0a77181976e045c441e4716144988ccf7cb308ef9820f4011143712250801122101ffdcb7da910966808d2d3bb3fd307b689c3ad49b9fde1424896c12063a84b75f12250801122101676d00d395acdcc0dec167c1a3ccf45fa415737faee5b74e8754df794a88b64d1225080112210105ed2c700945fe28a9fd7552975cd76e047454319f029bbf5be265c9bc54554b1225080112210154350e9d386d3ec494f76d0ce140dccb32a12fcf150745aab95471a2cee21fb1122508011221015a82302f68e12cbba17ccab8920ab5a100d9770a1504fe6b8d066beccd659745122508011221012d64758d6682c0d72a498d55be1ec1447b47cd6abf1d4ea8d4872c68dfdd11ef1225080112210116dc6e2093bc12c50a487ce251d8f1a5b3a1af59c3eb7132adbcba9f1fa778bb122508011221012dc2849158c9807287ecad05813a751ad863c4b7f66a243b66e991586bfccaf5122708011201011a20b6741f49d2db5052180ad02cca231c6aeac1333d515d6c490dac6e770278f638122508011221019a586bc3ee20b13fd03bf5b2a4461d5dd6fc5cf05c4c9c57303216e99dfbe239122708011201011a206dfada962670bb53945431e85063e191d5dc0fb6f19207d0a03d1055f801ad911225080112210119a4d2d17a37faf0605c8ac65cb4aac72de3d7779c64c8b78577df090685d442122708011201011a206db2b5ae7a1de14f4a8f779f0f12a4b67357945d3c15ecd7271aaf07a74e2dfa122708011201011a20d19a3c11a42b447b179bcfc7431a943cc3f597981a6c6dd91f994e1901e752d41225080112210118a3123f008e521520843625006577c5112f13fe624851e68a75613b7ac1a9e8122708011201011a2007b9aed070bfa3929d6dd5a4ab0d002c36e8a467f3d94e0d1b0d31773fd704d1122708011201011a207ec97d7e83fc505c030b81e395a5b19c1be86ed9f9dcd1fbb88e5edc5cbc6ad51225080112210168b051546044bfd33fc353d9a1b51b3afb762d3e27bfc475857f4295038e3254122708011201011a20eceb5dad8441fb687bf912c86ef77e3450902da06974913d4cb9881edd19a25212250801122101023ab1561db5979c5f009da8950a89b1b2c46bfe483bfda8d74d408a9564f04012250801122101ad0c58847b38b345ddd65b451ba0718df445572144eb2d5bab8225320a4d3869122708011201011a20a9672370788bd4c3b21487e1ff7daf9fd29055c33ef245e0d7ffbf29423afa0a122508011221017f42ba0ab9cf7c3328509a669ff3f005fff65768eda3c78a08b507aa291e9f6d12250801122101550e4a13c7e10998bd0f28e012103c375eb83d02f870868e199a7c32d741c9b012250801122101ad81a0c099cd1f93e449fa2f4aa848c28e34fb0e4abc32d88fa05507418592cd122508011221014fbe2d9c3066bf90ee87f5286b5adbe15b2b24ee71d39d1e975e24c964aef074122708011201011a200279a632ab7ad843f7aefc02c89d48423f765997719f2307177f9434e9f5845a122508011221010a5a5481f3a9523d353374777c2824c8487e4fad776105fb77d7fa2a11ab5732122508011221018015c60e22701c790051b93199dcd790c1733d79910898c85ced29e2ea03c464122708011201011a2046580f4438d7970a757449a1a8d7ab19b278ba7c5fd5041ed202dbfb62cfe66612250801122101e78070ad5b6a3392a54d1b7f541ee6ffc0a80b4f1dcd0286095a8f6330ef8fb2122708011201011a20cad792e7f4ee64cce5847de67882c26578efbd13700c7b032979c711e838445512250801122101f00585ec6dba7a13f34f71b9493a0d6fc5591638b51848d004702ccd4f697a50122508011221010efd2907c3aff8dafb0f72da84ceb19376fa1bec5d305c32101885b61aad5e7b122708011201011a20beb48a5b68c0fe3e514b4de894c96364087812a55e8dbb81a25a9976d91ea839122708011201011a207829c213824cc50a7705b799054a848decd28dd78183683ec6b3b57e1a207f5d122708011201011a20b0d25f9fe186304e97f7a1892ac21caa48deac5750adba83e8e7a3ab68ae294e122708011201011a2093fe012ca5775953d19f43e1e12752b88532608588f6b07b0cda97014579d37e12250801122101ad0e0a75d718ee8919e1ec2dd1b8ca45166f8868bdec7f52cd9a09aa2953a946122508011221019f6407dbbfd7317dbbda4d25ed767c45e897bc245a5051f2e7d9f1ccd9afbdfa122708011201011a207a147bea1ab0387504da2f907246d88cb8fd53ddb2cf994f9f7a86a053a18deb122708011201011a2001e07e7bf8b20cf9066b74cddee526edd36d760371a64bd11ba37339a4996b56122708011201011a20378eed6ef4ef986fd3d7ecc60b06fcb5bd991c51cc3b5fe7c2bb1ba5737f8ee4122708011201011a20ab1fbe82c840394b173785b166a6b40a71a3aedc24faed220c9d33d93501aec0122508011221018b014adefc2221a8fcda04c892040142485f69b15d85328789f94c9c6d65ce4c122708011201011a20d05bd5732fc00ecb341952f6f55240f00e795da842cdc333d3e21502620c6c03122708011201011a20cb5777a5c3853d79d3ba5a6a3bddab7d4bd3a18ef5e643742967b4b51a1f03cf122708011201011a20a6646e092d8a0fcaf26dc966b9b34987fc90bdcd5559a9182ce2671466b333b8122708011201011a20ddf7b89fbbae808f635f9f59f10fe3f29ebe2d9240158c7a0872bbfedcf02836122708011201011a206180367e0ef1e3eeb5b068ab5f27e59a581a516a40da40f4aebb8f6bd29923e912250801122101f28dcc2838635eddf2bc18727e1a0bbe6decb542a24c14f4732f793cc721b5a712250801122101c5b198042ebb553554734a4bfd8e11ff6682d7ee6638843153acce1d3666422f122508011221015074b5597289337449fd4e5198114ee3f8fd435204441bbd95ebc9ef1ba91874122508011221013182a16a4ab4e353d7e1c5f19e4bc32ddc94edc6ed22e1c82e28bf15733725a71225080112210115ea70cee62d2f5efdcb63881f3b493d1996f7ad61fed31af16f3d164229e481122708011201011a20d58a02ed02aa73394de38e275f99d8dd5ea5e71d5dd673bcb403e66b304294bf122708011201011a20c95ac9668a34761ccdd111d856992b20a0846b3e5e0e0a22121b752c591b7613122708011201011a203ae55f08905c68a2adbcdeacb26de2d609bd3e869ac66bac631e9502c92ae8f512250801122101fb082f2df8a2307274e40a7016cee71ade05e54f5558ed4f6c39991d4eb5c117122508011221018b7196f52f76efcbb7ab0467d1414a38bdc3301c978dbc5b326795d1bf431482122708011201011a20c4921f1afa5739d3a359f971e40a431a98b0188dd4b18f160ded84545769ba34122708011201011a20f8077d7c466da631d21ca54e1544db9ce6a2a4fd15145ec12fbc4adfc8e26628122708011201011a20d36e2a921c9f7e87f5b765185a991a4749ade4f99a6d5ac857f38665ae2ac3cc122708011201011a200ce4eb85cd6410e4c5e303948cae5a95522127b5a7fb491bf067f99e95ab6b6a12250801122101dbbc1bb871e574e1e708abf438782a09b4d4b6e8286c50a388e9ee5e4852b390122708011201011a2041e849a4259c8a305a7759e67a8e6fc95bb621a07a471ecfd3dacd9e353d824f122508011221012b5a98832c7bc5dd54801e7e100706332d58e560208fb62b06f3a77ddbecf075122508011221010ae70fac14ef0aa1b4051938569745fb3eb470675659b974f4bf68bf9706a7c012250801122101be4bf66cd45a4c4aaa7ff3857c3a42814555c7f7ec772bb1064dba946c6b328312250801122101eaf378c5c63442c551b21d5b6e43d54be67d451e2d26908afc2ea2cc3ffe3b7d122708011201011a20950e2179c815bfd8907d58128a7ae7c97daa5ab575af4171f644c8099010ad6f122708011201011a20d47d2c30c8448077ffa573c2c35a006220d7608a871e818ad29d3716daf485b9122708011201011a202b2520f45c94631a59b98227c7747a212e4fcb5e4d524464c84e67ae67e1c28e122708011201011a20d4a6e9e4496a7cd271b0e307292f254b38499c76ab01dc848331527e069b093b12250801122101168ddc9f9d7a14ab6353e9d31cb9b26fd91d2752bc8c5e7414d1e1cc4161e9fb122708011201011a200c9b1918cd04d1dc8de6b4fbb6a971f78bac178c5321f963df0b59606148cf5c122708011201011a2008bec402582cd245831ef538bb6dcfb9f3de2e7c8cd3e4077ea056998dc379591225080112210151dd9cb84f73eb1fba6f402ab9c79de2f5e4808612f3a209764790c661c8328d122708011201011a201e1efde4d1f12bbfceef37c9d9ffb43116624975f0a9a28ca642d9c500a7c8c0122708011201011a206e668cd3ff566cbbebdc256e9fe214a381079b6b9f4377909b76cceab49952f6122708011201011a203978d57f079ea09d6d6d32710f019c4b09315375ed3ce1173e0667becb564c93122508011221011aeb41adebc824fb9df4b0f004133ea0068f8d6048dcb3435af8d7e803710dd4122708011201011a20bbaf5df03403cb51ddf9090316fd0d0ed1077412394f7a2861b5da7d8bc98ebf122708011201011a2043d773c45158fdb231c1ea4ebd2ec61457fa77a886abea1981a6de4d263d4e8b12250801122101265936384fa658c0148f1842b942b9a2b5ff05f91edba9b997984aa9780cb3821225080112210157204e13cd8146b61b0864d4ec1fb2926bc4207ce3729b716f225b346edef077122708011201011a204aa1b82cd090ce99c3666f16b801cf28efa0e1dacdd91b46348aaa36117ae997122708011201011a20932fa47c2c8611b852545d85a3714e5b84102a1817b3d32ea359fee69376fcc0122508011221014a7fb59a20c67de5c95d701741dcafb0b2b424587d95ba08a48ea2887cc0be9c122708011201011a20ded91efa4177fffdac2795e86b73c57c25b6e5e77d390c3877859b791f385811122708011201011a20a3ed532793078461e21b64376577f3789338ec5bab6cc6559aeb306e7f9e3242122708011201011a207169495e53d639cb5f13e370c122e8266a3430217295336f77b592dd39bfa701122508011221011a5daddc81b3d7410433820681e37ab2437f978703ca2775f844a2992cd5595d1225080112210109e6a3c6b1dbc32d1af5178a7baa3df1e31ccf8520255a4aca37e649d62fa3c612250801122101001dd12ced870d2db0527fcd98cfb45f1c04a8211ab7292374010b6b8f0c01d812250801122101e2579b69672d24b2c8ace967126eb5c293ef978e3938ea2d94eed4f5dbae70b3122708011201011a20e98e3bc7a05844a192e2a9361f277188aab93853abdf34419ddd7098c090d8f51225080112210184c49247fdc0aef20e8dfaf047010764e084c4ae6b8a449eaebd1a6927c1bc63122708011201011a205431165031aa3557730f1f05b3dc36c981a29816f4851814838017203f34627a12250801122101983b2afefe44d668c42a75d72a4b1a06facc2dc38610acef33a7438fa918a98b122708011201011a20eb3e05749d936ecf8b5c5a09c52b9b58a8895be01c96bad625bdb7cc5135693e122708011201011a206c3c861f0d62e4945af0703f988a1c8571c1fbbdaee993f8d8114642374952ea122708011201011a2021e74bfc0537e1797d39980b1199b995c02a3d00dd4e7a84e72dbe8bc5aaf1d11225080112210137bef4dd27c2de86a41e7d487c2948ac12513bc72e3412ede04ca8526d102620122508011221010d1c82784b297bc946c7374232bdd741b26c73254271bc1d76c9e5e15e639ff6122708011201011a20579bf4a18e5abe8afdae625fd7bb4a4f341079bb104e1885fb322bd003c570a4122708011201011a20ae1285d65eb55c18dea08d4f2ef0a28791036650049025ec07fe0697c0a35cfc122708011201011a207a249163982a35cb260955598c1b1f143ff4bbb2fca0464f39315bc57012023a12250801122101dbfdb2c64bddc6cfd01e6f3c0ddfd36b13de2fc4315bc269901623bfff6027a1122708011201011a2081ca61864da86da04206d60b2939fba9a6ad4bb870eef466817b0e30c24c00471225080112210187642824cab7c3bca0044843945dcd350c5a61c7906792127d671f48de5d74b612250801122101e4feb818b7962b4c285c88154e13c8f6abe76d423ac20625d203a0405515cde4122708011201011a20925fb91059591774f00c6811e744444d43a09871a3be861325a404e0e1c406bf12250801122101ced5a0edfbcbb8e31f8bb407ee4b0adb3589d4212526f21fa96902a6cca63e39122508011221014c577d59f564ec54507d8161e5b79d5a411f2c4b1ddf46610d8b5c85c77c0abf12250801122101ce89e96deed4edb3294ee79b61ef950658df0430643d7f8315f39328d782dc9f1225080112210153783e42e17fc0eb36a3f982a3fc1ddac5481ce0f32dc9c2ccef4242044c03cb122708011201011a202b71ecd92886968bec1e3fed4e38fc54970c5007afa577c986316ba7635e355b1225080112210145200a18f2534749cbae17b829c2017b9c5609f480f091174df38f22416796c0122708011201011a2025f9d3d32e3ef8611589c63760b1a0e529028e17fbb1d557f8d753744dd56a8a122708011201011a206cb1efe64f6a744a6df7eae9b5e4f3f6c8eace5fd8e62e39ca2efa55cdbd7716122708011201011a20d978e2a4250873127c9f23c6424683557785624be9d66ccd62fa3404c4a743ec122708011201011a20f454e11d5c5030462b435f2677d7514c96629d4cf97b6a7e7c6a0cd894e3bba912250801122101124e9eb2c6a0ec7f465527caf0d9f3bfbd26568d78f5dcaafac599ce22d59eef12250801122101e7fa82c24f93c1690f3e564b0a3f1b45eaed3c8f06bdcbc59a1fa416d7d5c820122508011221019efbbbf59c7ed77a5d3dc61b8b6f77178c2a2ed3ba6dc7fa61fffde02d19d3ee1225080112210185e5a25bf7906404130d2b57db9e68d8192919cf0ff186e694b1b019fd58ac88122708011201011a20388c501b4bda0c64c0a85d74d9ad1e7608de52b067a5d893ad83042aa0ffe5ad122708011201011a207b652e83c4d49c7f9476079ebde01742b61f724d51b8550d44ad2fa16e7d1044122708011201011a20879c5704e1df82bba5645ab26fce2d587d5a6f02079d0f43c349e9a4535672b8122708011201011a203ad0761e4792bc789662828ab3983b31f4a93acec2f90306139bf8f85269a30912250801122101afa7971e8ac0609e2709ae13f218c83c632264c318291b2327c1e163305be47b122708011201011a207a4bce1ca4d1704903682e21f34eee82624907005e9ddd04b9fb084a87ba90d4122708011201011a20fa1881d8ea106faf335443cf0d5d84527c9dd421261a90b47ef3329bd9e843021225080112210189ac47f9679cb5136d295b78135c584eedad4123f92fcc94a64042e6823b0d6d12250801122101b6932938bdc08d6c13168390915b0b25d3c1d7951f3c61fc1c8fa49aa83cd4cc12250801122101d1995a2c320859d1bd9aa030124ab0517efe6944199877d95e46f6f964b5675612250801122101f881a68647ce50b69bf6be83bae146818eff71f878fa8c4c029c55b5b74dd9a3122708011201011a2054d77251f3b9f9c182a697d6f7edb95df5c43b38fed17c1974de6173efd979b412250801122101881c6394330f1602650a5226eac69263760f6303c6fe57088eae4b7d2809c0fa122708011201011a2009584133a128b5cdd27d1902cd73bb26ba479f1465a45990745e1bfe1c0b364f12250801122101bd64f703ec247f0d05a2877cba5fd9054f906c77fc3c00748f9c70a293a69fa6122708011201011a2077171562898b61be985cac22245826cd3799c3f0d9e0c09b7bb189e507c9edc5122708011201011a2016755dc9c634c80daf33278047ecbb82c8c542f71f144df20174128a3c904b76122708011201011a20eec0fe7410e008660595e66453704a4b2cad1cbb0a2420587b671bcaad1a8fc412250801122101414e30f086e99fd26c84b8fc04a4e1c38c49391eb921a588b3da49266a4a81f7122508011221011218b892bcd51b07b3b3850a448137ae28d1069d52bfbdb4a089c63fd40c368e1225080112210133568cec91245ccfd99f706c0563da48ce20cbadd2b51e1321ca54d045a9eb69122708011201011a20387d3570b66fa4e33a67e0f9d1fae695ab443a2f390e85b33a9427e546a8aec5122708011201011a2072c11303abe2de4843f725e40b00c9a2dff73ad8d4154521023ed8c8739ff68d12250801122101fdbceb97af12f8a1b83c3b759c1fc825e88c6090dc0d6b9caea961f68dc72c87122708011201011a20d3ed620e0d585ba618305f599988e15462ec48a24f3ec7ce2a00dddbdab7d09312250801122101668e2886cb8f73ae5295f09f20c316c21d7e633be2dae7b5a01b7c01d2830634122708011201011a20cc864565c845b4b53f083f69dec68438cd7ec8b848d485ffb6e893fe23f7e9481225080112210164ee33c6aa4304be656d80def8076791f2dbc6b54dc0fa997b0a9115747946bc1225080112210177556c07ad032fd183a1978441759260a29024cad7bf3740a5ee6cdd430ce91b122508011221017c057e865671e80b6dcda27d853772a1dff6fb41a6faac19af955678c77777b0122508011221015703835cdc085a48af6a648f43cf8420e4c81b503bd027c04211ef214b16172612250801122101315cd538f57e740ae25dc64464e6d7e1046a8c0777d9bec2e43886fa93e806a91225080112210124658892b5eb1979411d9bd12c643c70ccc1b336019df99471052dbca80aadd61225080112210142da6f06c33256fe77868c5812f6670713cae0b316425a77095a4b6166144e11122708011201011a20912a404f9b2dc0f3f92bec59ce1c9fb4c996a7170ada989eed88ce99628d17b8122708011201011a20d4eb294bdcea1065c8b24d57b4d1cd26b78f5345876907eda5eadb3e3976711c122708011201011a20160954659cb302bdd5cdafba68e113d9722394d9123a9cad87d7f128b0ce82c8122708011201011a20dd3fb99172a19ad6216c1c37aa45454d1803edf2f8e7dad77183928e017d9b8d122708011201011a2094650fcc185f666d229c717f56d44c0f40e96edc97dc22241c12178bac1b7c2812250801122101081c87cf7e23e1684a1886c0b22632f781bfde116fe2532e9256745f387811fe122708011201011a20fa6fa443a12c046fde4c437512f93fa6298ef6caeb1a99a01ed4ec062e5c2cfb12250801122101027b83e2628c39fb8340f33201a369fd6829ab6bf8e377bcde10412edbe5d9cd122508011221014f7ff1a0ef376fc76fe17953326045fc55d15e0042bd2160a8ebe01707d5a010122708011201011a201bf04c90368e4d72789b28f7b92bd582ce1a57a0f7cca50354511301fc360954122708011201011a20cb212bf4e11cd0a802dac501b71e877a669972f5d5e42c872ca9a7212ce79f25122508011221010b0dd000cbdfaa449f6356d4c710f88fece010774a9cc37dc656006b6c57577e12250801122101d60ca8a578c0ff7c0ca1024e5f66384ba4b8d85b6eda74f9464a43802e099391122708011201011a20d48ecb49a8205bf745d2963dd049a18b1db6ecbb20804d3b082c35f223b45f1412250801122101781d8d6f9695c35e68f320e3c2c07daf4c2fcfc5424527eba12aaf3a5dee8cc1122708011201011a206a6a5ce23cfb2174b88722a33bebc75e6b19ddc2391b973765032589793e32e0122708011201011a208894e9af93c88db14468a9c521af8e9894dd83079685a9f5d7a96ed4354d736a122708011201011a20e130943aa2036bb38beb3a5a8c0adf3530e8faa8aa592631fab0bcdd4bdf3472122708011201011a2012e560a1834e04950797d61ad16ddca9afc18c7979b5b9334608d04dcd870c69122508011221013be828dff60654f87ea63d50ff15c8549c2f92f8091cdaf0c579c24e00dde22c", "root": "91343e9496c6b33823f631cfd502fe1c3c606bf9688c45e7514afe7401790f52" } diff --git a/testdata/smt/exist_left.json b/testdata/smt/exist_left.json index 7a852e69..a300ccf8 100644 --- a/testdata/smt/exist_left.json +++ b/testdata/smt/exist_left.json @@ -1,6 +1,6 @@ { - "key": "002de9b963c4dacf518eeea7b754d2baac1886ef2f2a8ac704c05a692f4bedd5", - "proof": "0ae5030a20002de9b963c4dacf518eeea7b754d2baac1886ef2f2a8ac704c05a692f4bedd5121e76616c75655f666f725f4445687a30613576355036616536514c376d64451a07080118012a0100222708011201011a20bc79ee59a60c4f08cc0216a5f64d39f871cd730b6983079429e91d9bcd57d470222708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad222708011201011a203112ffea611a3ef030f5ed8dafb8bcaf8e33bec16fff9027b1a0c718136de2d3222708011201011a20480983a2541b5527e1b5607e32f0597b12204d4973b5d9b498d1ff2a2350352b222708011201011a2097058f1bf50e2b47ad129fdaf2dfd53f88f81467dad54dabfcf0fbe8330c4e4c222708011201011a2008f6f1e45958b4780e1e0f7791315d44355eba4e519e2fb25c3dc48627a59a45222708011201011a20bb4f607cb62f20e673fdfad3e40a8b596db50dc7c34e65aba74eec37f791e886222708011201011a20fe97c3211b6a7eb3d859e754b373e89897a54f74244f0a84defc1df2a203dfd8222708011201011a202cab93bf9b91d25010972968d69b47ca9dfd5b4cea0c71310e0adced33acb19d222708011201011a2069ca519f1f2528c971a930cdd00b65c41762e8510ce3d4a998d4ad8ccf598984", + "key": "4445687a30613576355036616536514c376d6445", + "proof": "0adb030a144445687a30613576355036616536514c376d6445121e76616c75655f666f725f4445687a30613576355036616536514c376d64451a090801100118012a0100222708011201011a20bc79ee59a60c4f08cc0216a5f64d39f871cd730b6983079429e91d9bcd57d470222708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad222708011201011a203112ffea611a3ef030f5ed8dafb8bcaf8e33bec16fff9027b1a0c718136de2d3222708011201011a20480983a2541b5527e1b5607e32f0597b12204d4973b5d9b498d1ff2a2350352b222708011201011a2097058f1bf50e2b47ad129fdaf2dfd53f88f81467dad54dabfcf0fbe8330c4e4c222708011201011a2008f6f1e45958b4780e1e0f7791315d44355eba4e519e2fb25c3dc48627a59a45222708011201011a20bb4f607cb62f20e673fdfad3e40a8b596db50dc7c34e65aba74eec37f791e886222708011201011a20fe97c3211b6a7eb3d859e754b373e89897a54f74244f0a84defc1df2a203dfd8222708011201011a202cab93bf9b91d25010972968d69b47ca9dfd5b4cea0c71310e0adced33acb19d222708011201011a2069ca519f1f2528c971a930cdd00b65c41762e8510ce3d4a998d4ad8ccf598984", "root": "432d73b49019d8df5c7e38fd93288d0240a62a3c010e7217a4a74f5885c391d5", "value": "76616c75655f666f725f4445687a30613576355036616536514c376d6445" } diff --git a/testdata/smt/exist_middle.json b/testdata/smt/exist_middle.json index 90c0fba9..da67213b 100644 --- a/testdata/smt/exist_middle.json +++ b/testdata/smt/exist_middle.json @@ -1,6 +1,6 @@ { - "key": "e369afec196c525d9e7ce3a6a94c325d3fd29b3d863c9463c939e8c085ae8e1a", - "proof": "0a80040a20e369afec196c525d9e7ce3a6a94c325d3fd29b3d863c9463c939e8c085ae8e1a121e76616c75655f666f725f464a544d75787a575873713470436c46506e6b481a07080118012a010022250801122101c607dff72d77496a8088f58c886a59e2c2e115c18688c1ea21007fa8a9c884da2225080112210152491dba094231188b893d16b0b08ad25246d5147a7a62149186518712618054222708011201011a20000000000000000000000000000000000000000000000000000000000000000022250801122101e3a85febd896e193b7ba37bc638c46d69530de820647fccb40da8583473c8feb222508011221014baf41d85dc399f406edbe4374e6b767663e4680fee217bfbca889618b7a83dc222708011201011a204ed121ef20f0e1d65a8a5e7d9ed86844de0bfd82621f3325f60eb872e9e738ea222708011201011a20a7cd5e87f54353e0b8d36901ba175daf7c00ff05c00183f522e94850a39ac4ce222708011201011a205a927fe700b5feacbf30a7cd160533e326c513eedc8e1d000cd8a71abd8480f522250801122101d9423c60941997d2078abd897d53f09cb4a844c684bc6a38140c04d6869809de22250801122101b1de51ac7abc0e0e5bc6955c4223228d16aba8cdb6e59bfd111d0901595bc32b22250801122101edbbd22b093f48404d082448bd335028477d700b449450b6800708095f78b9d6", + "key": "464a544d75787a575873713470436c46506e6b48", + "proof": "0af6030a14464a544d75787a575873713470436c46506e6b48121e76616c75655f666f725f464a544d75787a575873713470436c46506e6b481a090801100118012a010022250801122101c607dff72d77496a8088f58c886a59e2c2e115c18688c1ea21007fa8a9c884da2225080112210152491dba094231188b893d16b0b08ad25246d5147a7a62149186518712618054222708011201011a20000000000000000000000000000000000000000000000000000000000000000022250801122101e3a85febd896e193b7ba37bc638c46d69530de820647fccb40da8583473c8feb222508011221014baf41d85dc399f406edbe4374e6b767663e4680fee217bfbca889618b7a83dc222708011201011a204ed121ef20f0e1d65a8a5e7d9ed86844de0bfd82621f3325f60eb872e9e738ea222708011201011a20a7cd5e87f54353e0b8d36901ba175daf7c00ff05c00183f522e94850a39ac4ce222708011201011a205a927fe700b5feacbf30a7cd160533e326c513eedc8e1d000cd8a71abd8480f522250801122101d9423c60941997d2078abd897d53f09cb4a844c684bc6a38140c04d6869809de22250801122101b1de51ac7abc0e0e5bc6955c4223228d16aba8cdb6e59bfd111d0901595bc32b22250801122101edbbd22b093f48404d082448bd335028477d700b449450b6800708095f78b9d6", "root": "d32dd06714f3cee110cdb37ad7bc4760d4e291a555160f54429f9f15ddb04c4d", "value": "76616c75655f666f725f464a544d75787a575873713470436c46506e6b48" } diff --git a/testdata/smt/exist_right.json b/testdata/smt/exist_right.json index 5aaad154..767d59c8 100644 --- a/testdata/smt/exist_right.json +++ b/testdata/smt/exist_right.json @@ -1,6 +1,6 @@ { - "key": "ffed47aeb9697fed0b7cb34fbe32e1659869afc95034196e43ab30653e7002b0", - "proof": "0ad1030a20ffed47aeb9697fed0b7cb34fbe32e1659869afc95034196e43ab30653e7002b0121e76616c75655f666f725f796c52704356713162706b4575786b526b68644f1a07080118012a0100222508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd2225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d32225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba22250801122101c0bda8822a881b6a6a1dc5016bb062a9dd434ee3fe1c9bfb5bc0247bd6aeb5b42225080112210138cb0f6ef907a179a530fba848bae9547bcc37b9207aead6f7ef44064900386c2225080112210108f120d84fa1d8b2e7cc080673b382cb29169dd6e954b090f9cb7a25195d59a422250801122101ad476a123e0e8fbbbd4a225e29b193af4ae64600ccba4cc37922fc5d09159963222508011221013ad52a705d9b923dd07047aea6ad1bc1327e7557210c77cf06bcab7833ae313622250801122101c3a40ac7ab7c6cd3f267981dcd75158053dcad700af423ac0541ac0d315b4e7b222508011221017176acbe6927c4797f9e0456b7073802ad015fa8a915712e87b22830b72a1f94", + "key": "796c52704356713162706b4575786b526b68644f", + "proof": "0ac7030a14796c52704356713162706b4575786b526b68644f121e76616c75655f666f725f796c52704356713162706b4575786b526b68644f1a090801100118012a0100222508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd2225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d32225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba22250801122101c0bda8822a881b6a6a1dc5016bb062a9dd434ee3fe1c9bfb5bc0247bd6aeb5b42225080112210138cb0f6ef907a179a530fba848bae9547bcc37b9207aead6f7ef44064900386c2225080112210108f120d84fa1d8b2e7cc080673b382cb29169dd6e954b090f9cb7a25195d59a422250801122101ad476a123e0e8fbbbd4a225e29b193af4ae64600ccba4cc37922fc5d09159963222508011221013ad52a705d9b923dd07047aea6ad1bc1327e7557210c77cf06bcab7833ae313622250801122101c3a40ac7ab7c6cd3f267981dcd75158053dcad700af423ac0541ac0d315b4e7b222508011221017176acbe6927c4797f9e0456b7073802ad015fa8a915712e87b22830b72a1f94", "root": "6177836ac520808df67bc402ae76382282f4f07a526a2ac25c409cf0380cad97", "value": "76616c75655f666f725f796c52704356713162706b4575786b526b68644f" } diff --git a/testdata/smt/nonexist_left.json b/testdata/smt/nonexist_left.json index 33859673..ebefc075 100644 --- a/testdata/smt/nonexist_left.json +++ b/testdata/smt/nonexist_left.json @@ -1,6 +1,6 @@ { - "key": "002c041fe1df37d806cc5b493bed02222d83b25ffebf9cb529b4524cc547fbeb", - "proof": "128a040a20002c041fe1df37d806cc5b493bed02222d83b25ffebf9cb529b4524cc547fbeb1ae5030a20002de9b963c4dacf518eeea7b754d2baac1886ef2f2a8ac704c05a692f4bedd5121e76616c75655f666f725f4445687a30613576355036616536514c376d64451a07080118012a0100222708011201011a205aa5f240071f196e8d21e38b3fa6e942d5c529cd5fa0eec85607ba8cd8e37985222708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad222708011201011a20074e19b2ce9887b188cabd61f0af10d699c206d4eee9c5e914bcfea5960439f8222708011201011a208c8012ca455d57135bea305ad1080cc0a9d8dec078a7813736ff871b40708a72222708011201011a200c70649c4ea15de4a2f2087a340fa93adb880f851d5465481349803315201ecd222708011201011a20ca5d1f4ee19172af78ff61c113336292c11c89884ead5b541f54cc53449e2edf222708011201011a2091a26f99a2852c72dd4a15c6b0444421a6d033f7f570f10c8c564bc3dce2fbc3222708011201011a206bdf78f09ef3fc2789b9a48e5e741e722dbf44050ec052de79135fbabf10ccd6222708011201011a20ecbc7b302eae49d180b8d1f1fb36e7c5d19f84ce3c5d9a84e4913ef73a9cbab2222708011201011a2010d3a9e28ea143c3b9910b1d40e6087e97520bc2a3dbe66a806bf214039fdb1b", + "key": "636c536e4d46714a4e6162776a7a5134356e6d4d", + "proof": "1280040a20002c041fe1df37d806cc5b493bed02222d83b25ffebf9cb529b4524cc547fbeb1adb030a144445687a30613576355036616536514c376d6445121e76616c75655f666f725f4445687a30613576355036616536514c376d64451a090801100118012a0100222708011201011a205aa5f240071f196e8d21e38b3fa6e942d5c529cd5fa0eec85607ba8cd8e37985222708011201011a206732b1eaa2cf07fbc94599aecc2df057d8efb0ccd775d86b6ea176bfaad367ad222708011201011a20074e19b2ce9887b188cabd61f0af10d699c206d4eee9c5e914bcfea5960439f8222708011201011a208c8012ca455d57135bea305ad1080cc0a9d8dec078a7813736ff871b40708a72222708011201011a200c70649c4ea15de4a2f2087a340fa93adb880f851d5465481349803315201ecd222708011201011a20ca5d1f4ee19172af78ff61c113336292c11c89884ead5b541f54cc53449e2edf222708011201011a2091a26f99a2852c72dd4a15c6b0444421a6d033f7f570f10c8c564bc3dce2fbc3222708011201011a206bdf78f09ef3fc2789b9a48e5e741e722dbf44050ec052de79135fbabf10ccd6222708011201011a20ecbc7b302eae49d180b8d1f1fb36e7c5d19f84ce3c5d9a84e4913ef73a9cbab2222708011201011a2010d3a9e28ea143c3b9910b1d40e6087e97520bc2a3dbe66a806bf214039fdb1b", "root": "50be82f8013965f595392462f6c68b4c1d3d3401210a1084f6f73e3e2caf0648", "value": "" } diff --git a/testdata/smt/nonexist_middle.json b/testdata/smt/nonexist_middle.json index 7813be6b..a1b1530e 100644 --- a/testdata/smt/nonexist_middle.json +++ b/testdata/smt/nonexist_middle.json @@ -1,6 +1,6 @@ { - "key": "ba46e91ed56ac7bea290f31a5b5492090243f111a536c49f589e978f2d3ee8df", - "proof": "12d1080a20ba46e91ed56ac7bea290f31a5b5492090243f111a536c49f589e978f2d3ee8df12b2030a20ba43cb0567c827f469cf599f2a9756a0da1793edb84b4821ec1f62d2c3798ae4121e76616c75655f666f725f676e4e34356d52326831367467786a646f38544e1a07080118012a0100222708011201011a20d9948e386372dc85899e1890e988d8e47677c0bc211c65b55b5f70134dc15b0f222708011201011a201c2caf7504cfca30f253fce9c82051c3dd167058b0e22d840f4d90d0a0b2a9f7222508011221012db282d912c7d3f1dfd2750db451ad6e8176abddef45eb41fe1830c8789c1700222708011201011a200bd4fd01f2784fc637cc886ec0db6c4465cd4b4c8eb7266aaf84e0127740af2c222508011221018bf18f4ddf61ff31cb450737f6cf733d53d40f99bc3da526071755c37cc08ee1222508011221017bc720cf72271f5ac20af7962453209d5278965672e2cfebe5135bf85187681222250801122101f8500cdcf5ae664bdefce1221c42a69cf057b071e34a0ab946526525d6f3bc4d222708011201011a2027e93aecb0ea7d88fc13ce568017187ee5f07361f4d90e03866fb7f3f37a396622250801122101346d7d14c3a5521852f37261f20e91af45c5c0f772c13917b67d6eb6be9171ea1af7040a20bad9d45cc85eb8f5f14437c4328664e61dc03c06d21d8930986ddc86381ad0ac121e76616c75655f666f725f7252507a47715765774a6d6a38706b43453274641a07080118012a0100222708011201011a2003414f6402648178d0e76d39250d2e4cee54ec1f16e451cb602756a0a3044507222508011221010000000000000000000000000000000000000000000000000000000000000000222508011221010000000000000000000000000000000000000000000000000000000000000000222708011201011a20000000000000000000000000000000000000000000000000000000000000000022250801122101000000000000000000000000000000000000000000000000000000000000000022250801122101f18e35df2f213a21db25d856f3532afb9b1f7f47073f6f009507ddacd6d7457c222708011201011a201c2caf7504cfca30f253fce9c82051c3dd167058b0e22d840f4d90d0a0b2a9f7222508011221012db282d912c7d3f1dfd2750db451ad6e8176abddef45eb41fe1830c8789c1700222708011201011a200bd4fd01f2784fc637cc886ec0db6c4465cd4b4c8eb7266aaf84e0127740af2c222508011221018bf18f4ddf61ff31cb450737f6cf733d53d40f99bc3da526071755c37cc08ee1222508011221017bc720cf72271f5ac20af7962453209d5278965672e2cfebe5135bf85187681222250801122101f8500cdcf5ae664bdefce1221c42a69cf057b071e34a0ab946526525d6f3bc4d222708011201011a2027e93aecb0ea7d88fc13ce568017187ee5f07361f4d90e03866fb7f3f37a396622250801122101346d7d14c3a5521852f37261f20e91af45c5c0f772c13917b67d6eb6be9171ea", + "key": "364e58393178705248554d796e514c465332ffff", + "proof": "12bd080a20ba46e91ed56ac7bea290f31a5b5492090243f111a536c49f589e978f2d3ee8df12a8030a14676e4e34356d52326831367467786a646f38544e121e76616c75655f666f725f676e4e34356d52326831367467786a646f38544e1a090801100118012a0100222708011201011a20d9948e386372dc85899e1890e988d8e47677c0bc211c65b55b5f70134dc15b0f222708011201011a201c2caf7504cfca30f253fce9c82051c3dd167058b0e22d840f4d90d0a0b2a9f7222508011221012db282d912c7d3f1dfd2750db451ad6e8176abddef45eb41fe1830c8789c1700222708011201011a200bd4fd01f2784fc637cc886ec0db6c4465cd4b4c8eb7266aaf84e0127740af2c222508011221018bf18f4ddf61ff31cb450737f6cf733d53d40f99bc3da526071755c37cc08ee1222508011221017bc720cf72271f5ac20af7962453209d5278965672e2cfebe5135bf85187681222250801122101f8500cdcf5ae664bdefce1221c42a69cf057b071e34a0ab946526525d6f3bc4d222708011201011a2027e93aecb0ea7d88fc13ce568017187ee5f07361f4d90e03866fb7f3f37a396622250801122101346d7d14c3a5521852f37261f20e91af45c5c0f772c13917b67d6eb6be9171ea1aed040a147252507a47715765774a6d6a38706b4345327464121e76616c75655f666f725f7252507a47715765774a6d6a38706b43453274641a090801100118012a0100222708011201011a2003414f6402648178d0e76d39250d2e4cee54ec1f16e451cb602756a0a3044507222508011221010000000000000000000000000000000000000000000000000000000000000000222508011221010000000000000000000000000000000000000000000000000000000000000000222708011201011a20000000000000000000000000000000000000000000000000000000000000000022250801122101000000000000000000000000000000000000000000000000000000000000000022250801122101f18e35df2f213a21db25d856f3532afb9b1f7f47073f6f009507ddacd6d7457c222708011201011a201c2caf7504cfca30f253fce9c82051c3dd167058b0e22d840f4d90d0a0b2a9f7222508011221012db282d912c7d3f1dfd2750db451ad6e8176abddef45eb41fe1830c8789c1700222708011201011a200bd4fd01f2784fc637cc886ec0db6c4465cd4b4c8eb7266aaf84e0127740af2c222508011221018bf18f4ddf61ff31cb450737f6cf733d53d40f99bc3da526071755c37cc08ee1222508011221017bc720cf72271f5ac20af7962453209d5278965672e2cfebe5135bf85187681222250801122101f8500cdcf5ae664bdefce1221c42a69cf057b071e34a0ab946526525d6f3bc4d222708011201011a2027e93aecb0ea7d88fc13ce568017187ee5f07361f4d90e03866fb7f3f37a396622250801122101346d7d14c3a5521852f37261f20e91af45c5c0f772c13917b67d6eb6be9171ea", "root": "771301eae8764c6147399a9944dd4454e865db8bc33e60f22bebea1c9bf7021e", "value": "" } diff --git a/testdata/smt/nonexist_right.json b/testdata/smt/nonexist_right.json index 0140f01d..33348db1 100644 --- a/testdata/smt/nonexist_right.json +++ b/testdata/smt/nonexist_right.json @@ -1,6 +1,6 @@ { - "key": "ffffedc8e4ee7f13c9892bf6277cdd60e4e8fad77abb37ca4f3b888a63b60df4", - "proof": "12c4040a20ffffedc8e4ee7f13c9892bf6277cdd60e4e8fad77abb37ca4f3b888a63b60df4129f040a20fffa9eb3a5e49b7261d86e27c0e1c17f39215887308f5e3ca48e3264b03d2a2f121e76616c75655f666f725f6b63395874466e5a4645784d416f4b6f37566c5a1a07080118012a010022250801122101b76263b0c4e8438e81f21cdbff1e21b894a3c0e4ea08a0deab7c1de3292cd16a222508011221010000000000000000000000000000000000000000000000000000000000000000222508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd2225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d32225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba22250801122101354656582d1a82da7965901b2035596704419e5d238def48fdc03950624ee5182225080112210123ea47d69d737db4713327399685b2b15fc605d8b9fc63dad042cc7e2ca86b88222508011221010f0393085c3dd349cc0f45cb559fae81a1c4f24231afcb2b5ae51fd89262149322250801122101c5c632712f2341f6a31c3db7420c52c8d34df31704ce55856377cd9f23226469222508011221019209817b26ad0a91845bcbbd42453be5a6ba6f1c47e462014d6de896feede6522225080112210146446f4723153a265d03a7a20f4b906738d1af822434e77189134f45f2b2a80f22250801122101680acaa83722e275ea78c80914940c67efd48e5da6b331c821aaa2eb0ae184ed", + "key": "68316d656864356a774f646f4f4264613530684e", + "proof": "12ba040a20ffffedc8e4ee7f13c9892bf6277cdd60e4e8fad77abb37ca4f3b888a63b60df41295040a146b63395874466e5a4645784d416f4b6f37566c5a121e76616c75655f666f725f6b63395874466e5a4645784d416f4b6f37566c5a1a090801100118012a010022250801122101b76263b0c4e8438e81f21cdbff1e21b894a3c0e4ea08a0deab7c1de3292cd16a222508011221010000000000000000000000000000000000000000000000000000000000000000222508011221013ae2d90a118dd6f8a42f4006817e777f22540e921df1d97ed334a8b9de92c6cd2225080112210156a62a015a84af9a33ca716f52ed414382bed27a70b00391f15a5471f94443d32225080112210144c48bf2a802195fba5164a7a6c171a9af7a114c7880136108a5544d82fbacba22250801122101354656582d1a82da7965901b2035596704419e5d238def48fdc03950624ee5182225080112210123ea47d69d737db4713327399685b2b15fc605d8b9fc63dad042cc7e2ca86b88222508011221010f0393085c3dd349cc0f45cb559fae81a1c4f24231afcb2b5ae51fd89262149322250801122101c5c632712f2341f6a31c3db7420c52c8d34df31704ce55856377cd9f23226469222508011221019209817b26ad0a91845bcbbd42453be5a6ba6f1c47e462014d6de896feede6522225080112210146446f4723153a265d03a7a20f4b906738d1af822434e77189134f45f2b2a80f22250801122101680acaa83722e275ea78c80914940c67efd48e5da6b331c821aaa2eb0ae184ed", "root": "7bfe3d7630eb1f47be11d1724abad7a1b5de70c7131e7ed8ed60d9656ea49886", "value": "" }