Skip to content

Commit f183be7

Browse files
authored
Merge pull request #6403 from obycode/feat/clarity-4
Setup for Clarity 4 and implement `contract-hash?`
2 parents f61ea59 + 1503a7e commit f183be7

File tree

61 files changed

+2765
-463
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2765
-463
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1212
- Add `stackerdb_timeout_secs` to miner config for limiting duration of StackerDB HTTP requests.
1313
- When determining a global transaction replay set, the state evaluator now uses a longest-common-prefix algorithm to find a replay set in the case where a single replay set has less than 70% of signer weight.
1414
- New endpoint /v3/tenures/blocks/ allowing retrieving the list of stacks blocks from a burn block
15+
- Creates epoch 3.3 and costs-4 in preparation for a hardfork to activate Clarity 4
16+
- Adds support for new Clarity 4 builtins (not activated until epoch 3.3):
17+
- `contract-hash?`
1518

1619
### Changed
1720

clarity-serialization/src/errors/analysis.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ pub enum CheckErrors {
195195
CouldNotDetermineResponseErrType,
196196
CouldNotDetermineSerializationType,
197197
UncheckedIntermediaryResponses,
198+
ExpectedContractPrincipalValue(Value),
198199

199200
CouldNotDetermineMatchTypes,
200201
CouldNotDetermineType,
@@ -533,10 +534,11 @@ impl DiagnosableError for CheckErrors {
533534
CheckErrors::UnionTypeValueError(expected_types, found_type) => format!("expecting expression of type {}, found '{}'", formatted_expected_types(expected_types), found_type),
534535
CheckErrors::ExpectedOptionalType(found_type) => format!("expecting expression of type 'optional', found '{found_type}'"),
535536
CheckErrors::ExpectedOptionalOrResponseType(found_type) => format!("expecting expression of type 'optional' or 'response', found '{found_type}'"),
536-
CheckErrors::ExpectedOptionalOrResponseValue(found_type) => format!("expecting expression of type 'optional' or 'response', found '{found_type}'"),
537+
CheckErrors::ExpectedOptionalOrResponseValue(found_value) => format!("expecting expression of type 'optional' or 'response', found '{found_value}'"),
537538
CheckErrors::ExpectedResponseType(found_type) => format!("expecting expression of type 'response', found '{found_type}'"),
538-
CheckErrors::ExpectedOptionalValue(found_type) => format!("expecting expression of type 'optional', found '{found_type}'"),
539-
CheckErrors::ExpectedResponseValue(found_type) => format!("expecting expression of type 'response', found '{found_type}'"),
539+
CheckErrors::ExpectedOptionalValue(found_value) => format!("expecting expression of type 'optional', found '{found_value}'"),
540+
CheckErrors::ExpectedResponseValue(found_value) => format!("expecting expression of type 'response', found '{found_value}'"),
541+
CheckErrors::ExpectedContractPrincipalValue(found_value) => format!("expecting contract principal value, found '{found_value}'"),
540542
CheckErrors::CouldNotDetermineResponseOkType => "attempted to obtain 'ok' value from response, but 'ok' type is indeterminate".into(),
541543
CheckErrors::CouldNotDetermineResponseErrType => "attempted to obtain 'err' value from response, but 'err' type is indeterminate".into(),
542544
CheckErrors::CouldNotDetermineMatchTypes => "attempted to match on an (optional) or (response) type where either the some, ok, or err type is indeterminate. you may wish to use unwrap-panic or unwrap-err-panic instead.".into(),

clarity-serialization/src/types/signatures.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,20 @@ impl TypeSignature {
432432
}
433433
}
434434

435+
pub fn new_string_ascii(len: usize) -> Result<TypeSignature> {
436+
let len = BufferLength::try_from(len)?;
437+
Ok(TypeSignature::SequenceType(SequenceSubtype::StringType(
438+
StringSubtype::ASCII(len),
439+
)))
440+
}
441+
442+
pub fn new_string_utf8(len: usize) -> Result<TypeSignature> {
443+
let len = StringUTF8Length::try_from(len)?;
444+
Ok(TypeSignature::SequenceType(SequenceSubtype::StringType(
445+
StringSubtype::UTF8(len),
446+
)))
447+
}
448+
435449
pub fn is_response_type(&self) -> bool {
436450
matches!(self, TypeSignature::ResponseType(_))
437451
}
@@ -455,7 +469,8 @@ impl TypeSignature {
455469
| StacksEpochId::Epoch25
456470
| StacksEpochId::Epoch30
457471
| StacksEpochId::Epoch31
458-
| StacksEpochId::Epoch32 => self.admits_type_v2_1(other),
472+
| StacksEpochId::Epoch32
473+
| StacksEpochId::Epoch33 => self.admits_type_v2_1(other),
459474
StacksEpochId::Epoch10 => Err(CheckErrors::Expects("epoch 1.0 not supported".into())),
460475
}
461476
}
@@ -664,7 +679,8 @@ impl TypeSignature {
664679
| StacksEpochId::Epoch25
665680
| StacksEpochId::Epoch30
666681
| StacksEpochId::Epoch31
667-
| StacksEpochId::Epoch32 => self.canonicalize_v2_1(),
682+
| StacksEpochId::Epoch32
683+
| StacksEpochId::Epoch33 => self.canonicalize_v2_1(),
668684
}
669685
}
670686

@@ -952,7 +968,8 @@ impl TypeSignature {
952968
| StacksEpochId::Epoch25
953969
| StacksEpochId::Epoch30
954970
| StacksEpochId::Epoch31
955-
| StacksEpochId::Epoch32 => Self::least_supertype_v2_1(a, b),
971+
| StacksEpochId::Epoch32
972+
| StacksEpochId::Epoch33 => Self::least_supertype_v2_1(a, b),
956973
StacksEpochId::Epoch10 => Err(CheckErrors::Expects("epoch 1.0 not supported".into())),
957974
}
958975
}

clarity/src/vm/analysis/arithmetic_checker/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl ArithmeticOnlyChecker<'_> {
178178
| StxGetAccount => Err(Error::FunctionNotPermitted(function)),
179179
Append | Concat | AsMaxLen | ContractOf | PrincipalOf | ListCons | Print
180180
| AsContract | ElementAt | ElementAtAlias | IndexOf | IndexOfAlias | Map | Filter
181-
| Fold | Slice | ReplaceAt => Err(Error::FunctionNotPermitted(function)),
181+
| Fold | Slice | ReplaceAt | ContractHash => Err(Error::FunctionNotPermitted(function)),
182182
BuffToIntLe | BuffToUIntLe | BuffToIntBe | BuffToUIntBe => {
183183
Err(Error::FunctionNotPermitted(function))
184184
}

clarity/src/vm/analysis/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ pub fn run_analysis(
153153
| StacksEpochId::Epoch25
154154
| StacksEpochId::Epoch30
155155
| StacksEpochId::Epoch31
156-
| StacksEpochId::Epoch32 => {
156+
| StacksEpochId::Epoch32
157+
| StacksEpochId::Epoch33 => {
157158
TypeChecker2_1::run_pass(&epoch, &mut contract_analysis, db, build_type_map)
158159
}
159160
StacksEpochId::Epoch10 => {

clarity/src/vm/analysis/read_only_checker/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ impl<'a, 'b> ReadOnlyChecker<'a, 'b> {
293293
| AsContract | Begin | FetchVar | GetStxBalance | StxGetAccount | GetTokenBalance
294294
| GetAssetOwner | GetTokenSupply | ElementAt | IndexOf | Slice | ReplaceAt
295295
| BitwiseAnd | BitwiseOr | BitwiseNot | BitwiseLShift | BitwiseRShift | BitwiseXor2
296-
| ElementAtAlias | IndexOfAlias => {
296+
| ElementAtAlias | IndexOfAlias | ContractHash => {
297297
// Check all arguments.
298298
self.check_each_expression_is_read_only(args)
299299
}

clarity/src/vm/analysis/type_checker/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ impl FunctionType {
4646
| StacksEpochId::Epoch25
4747
| StacksEpochId::Epoch30
4848
| StacksEpochId::Epoch31
49-
| StacksEpochId::Epoch32 => self.check_args_2_1(accounting, args, clarity_version),
49+
| StacksEpochId::Epoch32
50+
| StacksEpochId::Epoch33 => self.check_args_2_1(accounting, args, clarity_version),
5051
StacksEpochId::Epoch10 => {
5152
Err(CheckErrors::Expects("Epoch10 is not supported".into()).into())
5253
}
@@ -71,7 +72,8 @@ impl FunctionType {
7172
| StacksEpochId::Epoch25
7273
| StacksEpochId::Epoch30
7374
| StacksEpochId::Epoch31
74-
| StacksEpochId::Epoch32 => {
75+
| StacksEpochId::Epoch32
76+
| StacksEpochId::Epoch33 => {
7577
self.check_args_by_allowing_trait_cast_2_1(db, clarity_version, func_args)
7678
}
7779
StacksEpochId::Epoch10 => {
@@ -92,6 +94,6 @@ fn is_reserved_word_v3(word: &str) -> bool {
9294
pub fn is_reserved_word(word: &str, version: ClarityVersion) -> bool {
9395
match version {
9496
ClarityVersion::Clarity1 | ClarityVersion::Clarity2 => false,
95-
ClarityVersion::Clarity3 => is_reserved_word_v3(word),
97+
ClarityVersion::Clarity3 | ClarityVersion::Clarity4 => is_reserved_word_v3(word),
9698
}
9799
}

clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ fn check_contract_call(
409409
_ => {
410410
return Err(
411411
CheckErrors::TraitReferenceUnknown(trait_instance.to_string()).into(),
412-
)
412+
);
413413
}
414414
};
415415

@@ -778,10 +778,10 @@ impl TypedNativeFunction {
778778
| StringToUInt | IntToAscii | IntToUtf8 | GetBurnBlockInfo | StxTransferMemo
779779
| StxGetAccount | BitwiseAnd | BitwiseOr | BitwiseNot | BitwiseLShift
780780
| BitwiseRShift | BitwiseXor2 | Slice | ToConsensusBuff | FromConsensusBuff
781-
| ReplaceAt | GetStacksBlockInfo | GetTenureInfo => {
781+
| ReplaceAt | GetStacksBlockInfo | GetTenureInfo | ContractHash => {
782782
return Err(CheckErrors::Expects(
783783
"Clarity 2+ keywords should not show up in 2.05".into(),
784-
))
784+
));
785785
}
786786
};
787787

clarity/src/vm/analysis/type_checker/v2_1/contexts.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ impl TraitContext {
4040
pub fn new(clarity_version: ClarityVersion) -> TraitContext {
4141
match clarity_version {
4242
ClarityVersion::Clarity1 => Self::Clarity1(HashMap::new()),
43-
ClarityVersion::Clarity2 | ClarityVersion::Clarity3 => Self::Clarity2 {
44-
defined: HashSet::new(),
45-
all: HashMap::new(),
46-
},
43+
ClarityVersion::Clarity2 | ClarityVersion::Clarity3 | ClarityVersion::Clarity4 => {
44+
Self::Clarity2 {
45+
defined: HashSet::new(),
46+
all: HashMap::new(),
47+
}
48+
}
4749
}
4850
}
4951

clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ fn check_contract_call(
498498
_ => {
499499
return Err(
500500
CheckErrors::TraitReferenceUnknown(trait_instance.to_string()).into(),
501-
)
501+
);
502502
}
503503
};
504504

@@ -576,7 +576,7 @@ fn check_contract_call(
576576
return Err(CheckErrors::TraitReferenceUnknown(
577577
trait_instance.to_string(),
578578
)
579-
.into())
579+
.into());
580580
}
581581
};
582582

@@ -1171,6 +1171,18 @@ impl TypedNativeFunction {
11711171
FromConsensusBuff => Special(SpecialNativeFunction(
11721172
&conversions::check_special_from_consensus_buff,
11731173
)),
1174+
ContractHash => Simple(SimpleNativeFunction(FunctionType::Fixed(FixedFunction {
1175+
args: vec![FunctionArg::new(
1176+
TypeSignature::PrincipalType,
1177+
ClarityName::try_from("contract".to_owned()).map_err(|_| {
1178+
CheckErrors::Expects(
1179+
"FAIL: ClarityName failed to accept default arg name".into(),
1180+
)
1181+
})?,
1182+
)],
1183+
returns: TypeSignature::new_response(BUFF_32.clone(), TypeSignature::UIntType)
1184+
.map_err(|_| CheckErrors::Expects("Bad constructor".into()))?,
1185+
}))),
11741186
};
11751187

11761188
Ok(out)

0 commit comments

Comments
 (0)