Skip to content

Commit

Permalink
fix: optimize proof.check_against_spec()
Browse files Browse the repository at this point in the history
  • Loading branch information
dinhbx-smartosc committed Apr 16, 2024
1 parent 3ed7664 commit 9b84cf9
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 38 deletions.
47 changes: 25 additions & 22 deletions cardano/lib/ibc/core/ics-023-vector-commitments/ics23/ops.ak
Expand Up @@ -3,7 +3,7 @@ use aiken/bytearray
use aiken/list
use ibc/core/ics_023_vector_commitments/ics23/constants.{hash_op_no_hash}
use ibc/core/ics_023_vector_commitments/ics23/proofs.{
HashOp, InnerOp, LeafOp, LengthOp, ProofSpec,
HashOp, InnerOp, InnerSpec, LeafOp, LengthOp, ProofSpec,
}
use ibc/utils/bytes.{encode_varint, has_prefix}

Expand All @@ -25,16 +25,18 @@ pub fn apply_inner_op(op: InnerOp, child: ByteArray) -> ByteArray {
}

/// check_against_spec_leaf_op() will verify the LeafOp is in the format defined in spec
pub fn check_against_spec_leaf_op(op: LeafOp, spec: ProofSpec) -> Bool {
expect spec != proofs.null_proof_spec()
pub fn check_against_spec_leaf_op(
op: LeafOp,
spec: ProofSpec,
is_iavl_spec: Bool,
) -> Bool {
let lspec = spec.leaf_spec
expect lspec != proofs.null_leaf_op()
expect op.hash == lspec.hash
expect op.prehash_key == lspec.prehash_key
expect op.prehash_value == lspec.prehash_value
expect op.length == lspec.length
expect has_prefix(op.prefix, lspec.prefix)
if validate_spec(spec) {
if is_iavl_spec {
expect validate_iavl_ops_leaf_op(op, 0)
True
} else {
Expand All @@ -43,23 +45,24 @@ pub fn check_against_spec_leaf_op(op: LeafOp, spec: ProofSpec) -> Bool {
}

/// check_against_spec_inner_op() will verify the InnerOp is in the format defined in spec
pub fn check_against_spec_inner_op(op: InnerOp, spec: ProofSpec, b: Int) -> Bool {
expect spec != proofs.null_proof_spec()
expect spec.inner_spec != proofs.null_inner_spec()
expect spec.leaf_spec != proofs.null_leaf_op()
expect op.hash == spec.inner_spec.hash
let leaf_prefix = spec.leaf_spec.prefix
expect !has_prefix(op.prefix, leaf_prefix)
expect bytearray.length(op.prefix) >= spec.inner_spec.min_prefix_length
let max_left_child_bytes =
( list.length(spec.inner_spec.child_order) - 1 ) * spec.inner_spec.child_size
expect
bytearray.length(op.prefix) <= spec.inner_spec.max_prefix_length + max_left_child_bytes
expect spec.inner_spec.child_size >= 1
expect bytearray.length(op.suffix) % spec.inner_spec.child_size == 0
if validate_spec(spec) {
expect validate_iavl_ops_inner_op(op, b)
True
pub fn check_against_spec_inner_op(
op: InnerOp,
spec: ProofSpec,
b: Int,
inner_spec: InnerSpec,
max_op_prefix_length: Int,
is_iavl_spec: Bool,
) -> Bool {
expect op.hash == inner_spec.hash

expect !has_prefix(op.prefix, spec.leaf_spec.prefix)

expect bytearray.length(op.prefix) >= inner_spec.min_prefix_length
expect bytearray.length(op.prefix) <= max_op_prefix_length
expect bytearray.length(op.suffix) % inner_spec.child_size == 0

if is_iavl_spec {
validate_iavl_ops_inner_op(op, b)
} else {
True
}
Expand Down
46 changes: 42 additions & 4 deletions cardano/lib/ibc/core/ics-023-vector-commitments/ics23/ops_test.ak
@@ -1,3 +1,4 @@
use aiken/list
use ibc/core/ics_023_vector_commitments/ics23/ops
use ibc/core/ics_023_vector_commitments/ics23/proof
use ibc/core/ics_023_vector_commitments/ics23/proofs.{
Expand Down Expand Up @@ -223,7 +224,11 @@ test test_check_against_spec_leaf_op_success() {
length: 1,
prefix: #"000202",
}
ops.check_against_spec_leaf_op(leaf, proofs.iavl_spec())

let spec = proofs.iavl_spec()
let is_iavl_spec = proofs.spec_equals(spec, proofs.iavl_spec())

ops.check_against_spec_leaf_op(leaf, spec, is_iavl_spec)
}

test test_check_against_spec_leaf_op_fail_with_other_spec() fail {
Expand All @@ -235,7 +240,11 @@ test test_check_against_spec_leaf_op_fail_with_other_spec() fail {
length: 1,
prefix: #"000202",
}
ops.check_against_spec_leaf_op(leaf, proofs.iavl_spec())

let spec = proofs.iavl_spec()
let is_iavl_spec = proofs.spec_equals(spec, proofs.iavl_spec())

ops.check_against_spec_leaf_op(leaf, spec, is_iavl_spec)
}

test test_check_against_spec_inner_op_success() {
Expand All @@ -245,7 +254,22 @@ test test_check_against_spec_inner_op_success() {
prefix: #"04060220",
suffix: #"20afca3de8c7aefe1041f185a34e977a976b37d6ce4cce80e5e4545b93413eca02",
}
ops.check_against_spec_inner_op(inner_op, proofs.iavl_spec(), 1)

let spec = proofs.iavl_spec()
let inner_spec = spec.inner_spec
let max_op_prefix_length =
( list.length(inner_spec.child_order) - 1 ) * inner_spec.child_size + inner_spec.max_prefix_length

let is_iavl_spec = proofs.spec_equals(spec, proofs.iavl_spec())

ops.check_against_spec_inner_op(
inner_op,
spec,
1,
spec.inner_spec,
max_op_prefix_length,
is_iavl_spec,
)
}

test test_check_against_spec_inner_op_fail_with_other_spec() fail {
Expand All @@ -255,7 +279,21 @@ test test_check_against_spec_inner_op_fail_with_other_spec() fail {
prefix: #"04060220",
suffix: #"20afca3de8c7aefe1041f185a34e977a976b37d6ce4cce80e5e4545b93413eca02",
}
ops.check_against_spec_inner_op(inner_op, proofs.tendermint_spec(), 1)
let spec = proofs.tendermint_spec()
let inner_spec = spec.inner_spec
let max_op_prefix_length =
( list.length(inner_spec.child_order) - 1 ) * inner_spec.child_size + inner_spec.max_prefix_length

let is_iavl_spec = proofs.spec_equals(spec, proofs.iavl_spec())

ops.check_against_spec_inner_op(
inner_op,
spec,
1,
spec.inner_spec,
max_op_prefix_length,
is_iavl_spec,
)
}

test test_apply_leaf_op_success_with_only_hash() {
Expand Down
24 changes: 22 additions & 2 deletions cardano/lib/ibc/core/ics-023-vector-commitments/ics23/proof.ak
Expand Up @@ -138,18 +138,38 @@ fn calculate_exist_internal(

/// check_against_spec() will verify the leaf and all path steps are in the format defined in spec
pub fn check_against_spec(p: ExistenceProof, spec: ProofSpec) -> Bool {
expect spec != proofs.null_proof_spec()
expect spec.leaf_spec != proofs.null_leaf_op()

let is_iavl_spec = proofs.spec_equals(spec, proofs.iavl_spec())

let leaf = get_leaf_existence_proof(p)
expect leaf != proofs.null_leaf_op()
expect ops.check_against_spec_leaf_op(leaf, spec)
expect ops.check_against_spec_leaf_op(leaf, spec, is_iavl_spec)
expect !(spec.min_depth > 0 && list.length(p.path) < spec.min_depth)
expect !(spec.max_depth > 0 && list.length(p.path) > spec.max_depth)

let inner_spec = spec.inner_spec
expect inner_spec != proofs.null_inner_spec()

let max_op_prefix_length =
( list.length(inner_spec.child_order) - 1 ) * inner_spec.child_size + inner_spec.max_prefix_length

let layer_num = 1
let accum_layer_num =
list.reduce(
p.path,
layer_num,
fn(accum_layer_num, inner) {
expect ops.check_against_spec_inner_op(inner, spec, layer_num)
expect
ops.check_against_spec_inner_op(
inner,
spec,
layer_num,
inner_spec,
max_op_prefix_length,
is_iavl_spec,
)
accum_layer_num + 1
},
)
Expand Down
12 changes: 2 additions & 10 deletions cardano/lib/ibc/core/ics-023-vector-commitments/ics23/proofs.ak
Expand Up @@ -67,19 +67,11 @@ pub type CommitmentRoot =
ByteArray

pub fn get_prefix_leaf_op(m: LeafOp) -> ByteArray {
if m != null_leaf_op() {
m.prefix
} else {
#[]
}
m.prefix
}

pub fn get_prefix_inner_op(m: InnerOp) -> ByteArray {
if m != null_inner_op() {
m.prefix
} else {
#[]
}
m.prefix
}

pub fn null_leaf_op() -> LeafOp {
Expand Down

0 comments on commit 9b84cf9

Please sign in to comment.