fix: canonicalize types when checking contract-call

This commit is contained in:
Brice Dobry
2023-01-20 17:30:27 -05:00
parent d89fbb2a37
commit 3d1a834116
3 changed files with 16 additions and 15 deletions

View File

@@ -175,10 +175,10 @@ impl DefinedFunction {
for arg in arg_iterator.drain(..) {
let ((name, type_sig), value) = arg;
let canonical_sig = type_sig.canonicalize_simple_type(env.epoch());
// Clarity 1 behavior
if *env.contract_context.get_clarity_version() < ClarityVersion::Clarity2 {
match (type_sig, value) {
match (&canonical_sig, value) {
// Epoch < 2.1 uses TraitReferenceType
(
TypeSignature::TraitReferenceType(trait_identifier),
@@ -212,9 +212,9 @@ impl DefinedFunction {
);
}
_ => {
if !type_sig.admits(env.epoch(), value)? {
if !canonical_sig.admits(env.epoch(), value)? {
return Err(CheckErrors::TypeValueError(
type_sig.clone(),
canonical_sig.clone(),
value.clone(),
)
.into());
@@ -231,9 +231,9 @@ impl DefinedFunction {
// e.g. `(some .foo)` to `(optional <trait>`)
// and traits can be implicitly cast to sub-traits
// e.g. `<foo-and-bar>` to `<foo>`
let cast_value = clarity2_implicit_cast(type_sig, value)?;
let cast_value = clarity2_implicit_cast(&canonical_sig, value)?;
match (&type_sig, &cast_value) {
match (&canonical_sig, &cast_value) {
(
TypeSignature::CallableType(CallableSubtype::Trait(_)),
Value::CallableContract(CallableData {
@@ -253,9 +253,9 @@ impl DefinedFunction {
);
}
_ => {
if !type_sig.admits(env.epoch(), &cast_value)? {
if !canonical_sig.admits(env.epoch(), &cast_value)? {
return Err(
CheckErrors::TypeValueError(type_sig.clone(), cast_value).into()
CheckErrors::TypeValueError(canonical_sig.clone(), cast_value).into()
);
}
}

View File

@@ -356,7 +356,7 @@ impl TypeSignature {
.ok_or_else(|| CheckErrors::ValueTooLarge)?
}
TypeSignature::PrincipalType
| TypeSignature::CallableType(CallableSubtype::Principal(_))
| TypeSignature::CallableType(_)
| TypeSignature::TraitReferenceType(_) => {
// version byte + 20 byte hash160
let maximum_issuer_size = 21;
@@ -412,8 +412,7 @@ impl TypeSignature {
};
cmp::max(ok_type_max_size, err_type_max_size)
}
TypeSignature::CallableType(CallableSubtype::Trait(_))
| TypeSignature::ListUnionType(_) => {
TypeSignature::ListUnionType(_) => {
return Err(CheckErrors::CouldNotDetermineSerializationType)
}
};

View File

@@ -455,9 +455,10 @@ impl TypeSignature {
}
pub fn admits_type(&self, epoch: &StacksEpochId, other: &TypeSignature) -> Result<bool> {
let canonical_other = other.canonicalize_simple_type(epoch);
match epoch {
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => self.admits_type_v2_0(other),
StacksEpochId::Epoch21 => self.admits_type_v2_1(other),
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => self.admits_type_v2_0(&canonical_other),
StacksEpochId::Epoch21 => self.admits_type_v2_1(&canonical_other),
StacksEpochId::Epoch10 => unreachable!("epoch 1.0 not supported"),
}
}
@@ -941,9 +942,10 @@ impl TypeSignature {
a: &TypeSignature,
b: &TypeSignature,
) -> Result<TypeSignature> {
let canonical_a = a.canonicalize_simple_type(epoch);
match epoch {
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => Self::least_supertype_v2_0(a, b),
StacksEpochId::Epoch21 => Self::least_supertype_v2_1(a, b),
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => Self::least_supertype_v2_0(&canonical_a, b),
StacksEpochId::Epoch21 => Self::least_supertype_v2_1(&canonical_a, b),
StacksEpochId::Epoch10 => unreachable!("Clarity 1.0 is not supported"),
}
}