Skip to content

Commit 25d083b

Browse files
committed
add generic digest opcode
1 parent 1c2c3a6 commit 25d083b

11 files changed

Lines changed: 62 additions & 5 deletions

File tree

src/compiler/expr.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ pub(crate) fn emit_expression_asm(expr: &Expression, asm: &mut Vec<String>) {
190190
emit_expression_asm(hash_type, asm);
191191
asm.push(OP_SIGHASH.to_string());
192192
}
193+
Expression::Digest { data, hash_type } => {
194+
emit_expression_asm(data, asm);
195+
emit_expression_asm(hash_type, asm);
196+
asm.push(OP_DIGEST.to_string());
197+
}
193198
// Byte-string concatenation: bytes-like + value → OP_CAT
194199
Expression::Concat {
195200
left,

src/compiler/loops.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,14 @@ pub(crate) fn substitute_expression(
283283
hash_type, index_var, value_var, k, array_name,
284284
)),
285285
},
286+
Expression::Digest { data, hash_type } => Expression::Digest {
287+
data: Box::new(substitute_expression(
288+
data, index_var, value_var, k, array_name,
289+
)),
290+
hash_type: Box::new(substitute_expression(
291+
hash_type, index_var, value_var, k, array_name,
292+
)),
293+
},
286294
Expression::ModExp {
287295
base,
288296
exponent,

src/compiler/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::models::{
44
};
55
use crate::opcodes::{
66
OP_0, OP_1, OP_8, OP_ADD, OP_BIN2NUM, OP_BOOLAND, OP_CAT, OP_CHECKLOCKTIMEVERIFY, OP_CHECKSIG,
7-
OP_CHECKSIGADD, OP_CHECKSIGFROMSTACK, OP_DIV, OP_DROP, OP_ECADD, OP_ECMUL,
7+
OP_CHECKSIGADD, OP_CHECKSIGFROMSTACK, OP_DIGEST, OP_DIV, OP_DROP, OP_ECADD, OP_ECMUL,
88
OP_ECMULSCALARVERIFY, OP_ECPAIRING, OP_ELSE, OP_ENDIF, OP_EQUAL, OP_EQUALVERIFY,
99
OP_FINDASSETGROUPBYASSETID, OP_GREATERTHAN, OP_GREATERTHANOREQUAL, OP_IF, OP_INSPECTASSETGROUP,
1010
OP_INSPECTASSETGROUPASSETID, OP_INSPECTASSETGROUPCTRL, OP_INSPECTASSETGROUPMETADATAHASH,

src/models/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,11 @@ pub enum Expression {
483483
},
484484
/// Signature hash for the current input under the selected hash type.
485485
Sighash { hash_type: Box<Expression> },
486+
/// Digest selected at runtime. The result is 20 or 32 bytes depending on the hash type.
487+
Digest {
488+
data: Box<Expression>,
489+
hash_type: Box<Expression>,
490+
},
486491
// ─── Arithmetic ────────────────────────────────────────────────────
487492
/// Negate a BigNum value: negate(value)
488493
Negate { value: Box<Expression> },

src/opcodes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub const OP_SHA256FINALIZE: &str = "OP_SHA256FINALIZE";
4545
pub const OP_HASH160: &str = "OP_HASH160";
4646
pub const OP_HASH256: &str = "OP_HASH256";
4747
pub const OP_RIPEMD160: &str = "OP_RIPEMD160";
48+
pub const OP_DIGEST: &str = "OP_DIGEST";
4849

4950
// Byte-string manipulation
5051
pub const OP_CAT: &str = "OP_CAT";

src/parser/crypto.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ pub(crate) fn parse_sighash(pair: Pair<Rule>) -> Result<Expression, String> {
6666
})
6767
}
6868

69+
pub(crate) fn parse_digest(pair: Pair<Rule>) -> Result<Expression, String> {
70+
let mut inner = pair.into_inner();
71+
let data = parse_additive_expr(inner.next().ok_or("Missing data in digest")?)?;
72+
let hash_type = parse_atom_pair(inner.next().ok_or("Missing hash type in digest")?);
73+
Ok(Expression::Digest {
74+
data: Box::new(data),
75+
hash_type: Box::new(hash_type),
76+
})
77+
}
78+
6979
// ─── Arithmetic Parsing ────────────────────────────────────────────────
7080

7181
/// Parse negate(value) → Expression::Negate

src/parser/expr.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ pub(crate) fn reserved_function_signature(name: &str) -> Option<&'static str> {
147147
"sha256Initialize" => Some("sha256Initialize(data)"),
148148
"sha256Update" => Some("sha256Update(ctx, chunk)"),
149149
"sha256Finalize" => Some("sha256Finalize(ctx, lastChunk)"),
150+
"digest" => Some("digest(data, hashType)"),
150151
"sighash" => Some("sighash(hashType)"),
151152
"negate" => Some("negate(value)"),
152153
"modExp" => Some("modExp(base, exponent, modulus)"),
@@ -214,6 +215,7 @@ pub(crate) fn parse_primary_expr(pair: Pair<Rule>) -> Result<Expression, String>
214215
Rule::sha256_initialize => parse_sha256_initialize(pair),
215216
Rule::sha256_update => parse_sha256_update(pair),
216217
Rule::sha256_finalize => parse_sha256_finalize(pair),
218+
Rule::digest_func => parse_digest(pair),
217219
Rule::sighash_func => parse_sighash(pair),
218220
// Arithmetic
219221
Rule::negate_func => parse_negate(pair),

src/parser/grammar.pest

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ primary_expr = {
136136
sha256_update |
137137
sha256_finalize |
138138
sha256_func |
139+
digest_func |
139140
sighash_func |
140141
negate_func |
141142
mod_exp_func |
@@ -196,6 +197,7 @@ complex_expression = _{
196197
sha256_initialize |
197198
sha256_update |
198199
sha256_finalize |
200+
digest_func |
199201
sighash_func |
200202
negate_func |
201203
mod_exp_func |
@@ -512,6 +514,10 @@ sighash_func = {
512514
"sighash" ~ "(" ~ (identifier | number_literal) ~ ")"
513515
}
514516

517+
digest_func = {
518+
"digest" ~ "(" ~ additive_expr ~ "," ~ (identifier | number_literal) ~ ")"
519+
}
520+
515521
// ─── Arithmetic ────────────────────────────────────────────────────────
516522

517523
// Negate a BigNum value: negate(value) → OP_NEGATE

src/typechecker/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ pub fn infer_type(expr: &Expression, scope: &Scope) -> ArkType {
546546
| Expression::Sighash { .. } => ArkType::Bytes32,
547547

548548
// Byte-string ops
549-
Expression::Concat { .. } => ArkType::Bytes,
549+
Expression::Concat { .. } | Expression::Digest { .. } => ArkType::Bytes,
550550

551551
// Arithmetic
552552
Expression::Negate { .. } | Expression::ModExp { .. } => ArkType::Int,

src/validator/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ fn child_exprs(expr: &Expression) -> Vec<&Expression> {
399399
last_chunk,
400400
} => vec![context, last_chunk],
401401
Expression::Sighash { hash_type } => vec![hash_type],
402+
Expression::Digest { data, hash_type } => vec![data, hash_type],
402403
Expression::Negate { value } => vec![value],
403404
Expression::ModExp {
404405
base,

0 commit comments

Comments
 (0)