Skip to content
This repository was archived by the owner on Jun 11, 2026. It is now read-only.

Commit e3fd37a

Browse files
authored
Merge pull request #10 from pragma-org/jshy/builtins
2 parents 749e873 + 32316d1 commit e3fd37a

12 files changed

Lines changed: 833 additions & 8 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uplc/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ publish = true
1414
blst = "0.3.13"
1515
bumpalo = { version = "3.16.0", features = ["collections"] }
1616
chumsky = { version = "=1.0.0-alpha.7", features = ["pratt"] }
17-
cryptoxide = "0.4.4"
17+
cryptoxide = { version = "0.4.4", features = ["ripemd160"] }
18+
hamming = "0.1.3"
1819
minicbor = { version = "0.25.1", features = ["std"] }
1920
num = "0.4.3"
2021
num-bigint = "0.4"

crates/uplc/src/builtin/default_function.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ pub enum DefaultFunction {
9898
// Bitwise
9999
IntegerToByteString = 73,
100100
ByteStringToInteger = 74,
101+
102+
AndByteString = 75,
103+
OrByteString = 76,
104+
XorByteString = 77,
105+
ComplementByteString = 78,
106+
ReadBit = 79,
107+
WriteBits = 80,
108+
ReplicateByte = 81,
109+
ShiftByteString = 82,
110+
RotateByteString = 83,
111+
CountSetBits = 84,
112+
FindFirstSetBit = 85,
113+
Ripemd_160 = 86,
101114
}
102115

103116
impl DefaultFunction {
@@ -178,6 +191,18 @@ impl DefaultFunction {
178191
DefaultFunction::Bls12_381_FinalVerify => 0,
179192
DefaultFunction::IntegerToByteString => 0,
180193
DefaultFunction::ByteStringToInteger => 0,
194+
DefaultFunction::AndByteString => 0,
195+
DefaultFunction::OrByteString => 0,
196+
DefaultFunction::XorByteString => 0,
197+
DefaultFunction::ComplementByteString => 0,
198+
DefaultFunction::ReadBit => 0,
199+
DefaultFunction::WriteBits => 0,
200+
DefaultFunction::ReplicateByte => 0,
201+
DefaultFunction::ShiftByteString => 0,
202+
DefaultFunction::RotateByteString => 0,
203+
DefaultFunction::CountSetBits => 0,
204+
DefaultFunction::FindFirstSetBit => 0,
205+
DefaultFunction::Ripemd_160 => 0,
181206
}
182207
}
183208

@@ -258,6 +283,18 @@ impl DefaultFunction {
258283
DefaultFunction::Bls12_381_FinalVerify => 2,
259284
DefaultFunction::IntegerToByteString => 3,
260285
DefaultFunction::ByteStringToInteger => 2,
286+
DefaultFunction::AndByteString => 3,
287+
DefaultFunction::OrByteString => 3,
288+
DefaultFunction::XorByteString => 3,
289+
DefaultFunction::ComplementByteString => 1,
290+
DefaultFunction::ReadBit => 2,
291+
DefaultFunction::WriteBits => 3,
292+
DefaultFunction::ReplicateByte => 2,
293+
DefaultFunction::ShiftByteString => 2,
294+
DefaultFunction::RotateByteString => 2,
295+
DefaultFunction::CountSetBits => 1,
296+
DefaultFunction::FindFirstSetBit => 1,
297+
DefaultFunction::Ripemd_160 => 1,
261298
}
262299
}
263300
}

crates/uplc/src/flat/data.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ impl<'a, 'b> minicbor::decode::Decode<'b, Ctx<'a>> for &'a PlutusData<'a> {
5353
}
5454
_ => {
5555
let e = minicbor::decode::Error::message(format!(
56-
"unknown tag for plutus data tag: {}",
57-
tag
56+
"unknown tag for plutus data tag: {tag}",
5857
));
5958

6059
Err(e)
@@ -76,7 +75,7 @@ impl<'a, 'b> minicbor::decode::Decode<'b, Ctx<'a>> for &'a PlutusData<'a> {
7675
if x == IanaTag::PosBignum {
7776
num_bigint::Sign::Plus
7877
} else {
79-
num_bigint::Sign::Plus
78+
num_bigint::Sign::Minus
8079
},
8180
&bytes,
8281
));

crates/uplc/src/machine/cost_model/builtin_costs.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@ pub struct BuiltinCosts {
9393
// bitwise
9494
integer_to_byte_string: ThreeArgumentsCosting,
9595
byte_string_to_integer: TwoArgumentsCosting,
96+
and_byte_string: ThreeArgumentsCosting,
97+
or_byte_string: ThreeArgumentsCosting,
98+
xor_byte_string: ThreeArgumentsCosting,
99+
complement_byte_string: OneArgumentCosting,
100+
read_bit: TwoArgumentsCosting,
101+
write_bits: ThreeArgumentsCosting,
102+
replicate_byte: TwoArgumentsCosting,
103+
shift_byte_string: TwoArgumentsCosting,
104+
rotate_byte_string: TwoArgumentsCosting,
105+
count_set_bits: OneArgumentCosting,
106+
find_first_set_bit: OneArgumentCosting,
107+
ripemd_160: OneArgumentCosting,
96108
}
97109

98110
impl Default for BuiltinCosts {
@@ -568,6 +580,87 @@ impl BuiltinCosts {
568580
)
569581
}
570582

583+
pub fn and_byte_string(&self, args: [i64; 3]) -> ExBudget {
584+
ExBudget::new(
585+
self.and_byte_string.mem.cost(args),
586+
self.and_byte_string.cpu.cost(args),
587+
)
588+
}
589+
590+
pub fn or_byte_string(&self, args: [i64; 3]) -> ExBudget {
591+
ExBudget::new(
592+
self.or_byte_string.mem.cost(args),
593+
self.or_byte_string.cpu.cost(args),
594+
)
595+
}
596+
597+
pub fn xor_byte_string(&self, args: [i64; 3]) -> ExBudget {
598+
ExBudget::new(
599+
self.xor_byte_string.mem.cost(args),
600+
self.xor_byte_string.cpu.cost(args),
601+
)
602+
}
603+
604+
pub fn complement_byte_string(&self, args: [i64; 1]) -> ExBudget {
605+
ExBudget::new(
606+
self.complement_byte_string.mem.cost(args),
607+
self.complement_byte_string.cpu.cost(args),
608+
)
609+
}
610+
611+
pub fn read_bit(&self, args: [i64; 2]) -> ExBudget {
612+
ExBudget::new(self.read_bit.mem.cost(args), self.read_bit.cpu.cost(args))
613+
}
614+
615+
pub fn write_bits(&self, args: [i64; 3]) -> ExBudget {
616+
ExBudget::new(
617+
self.write_bits.mem.cost(args),
618+
self.write_bits.cpu.cost(args),
619+
)
620+
}
621+
622+
pub fn replicate_byte(&self, args: [i64; 2]) -> ExBudget {
623+
ExBudget::new(
624+
self.replicate_byte.mem.cost(args),
625+
self.replicate_byte.cpu.cost(args),
626+
)
627+
}
628+
629+
pub fn shift_byte_string(&self, args: [i64; 2]) -> ExBudget {
630+
ExBudget::new(
631+
self.shift_byte_string.mem.cost(args),
632+
self.shift_byte_string.cpu.cost(args),
633+
)
634+
}
635+
636+
pub fn rotate_byte_string(&self, args: [i64; 2]) -> ExBudget {
637+
ExBudget::new(
638+
self.rotate_byte_string.mem.cost(args),
639+
self.rotate_byte_string.cpu.cost(args),
640+
)
641+
}
642+
643+
pub fn count_set_bits(&self, args: [i64; 1]) -> ExBudget {
644+
ExBudget::new(
645+
self.count_set_bits.mem.cost(args),
646+
self.count_set_bits.cpu.cost(args),
647+
)
648+
}
649+
650+
pub fn find_first_set_bit(&self, args: [i64; 1]) -> ExBudget {
651+
ExBudget::new(
652+
self.find_first_set_bit.mem.cost(args),
653+
self.find_first_set_bit.cpu.cost(args),
654+
)
655+
}
656+
657+
pub fn ripemd_160(&self, args: [i64; 1]) -> ExBudget {
658+
ExBudget::new(
659+
self.ripemd_160.mem.cost(args),
660+
self.ripemd_160.cpu.cost(args),
661+
)
662+
}
663+
571664
pub fn v3() -> Self {
572665
Self {
573666
add_integer: TwoArgumentsCosting::new(
@@ -880,6 +973,54 @@ impl BuiltinCosts {
880973
TwoArgumentsCosting::linear_in_y(0, 1),
881974
TwoArgumentsCosting::quadratic_in_y(1006041, 43623, 251),
882975
),
976+
and_byte_string: ThreeArgumentsCosting::new(
977+
ThreeArgumentsCosting::linear_in_max_y_z(0, 1),
978+
ThreeArgumentsCosting::linear_in_y_and_z(100181, 726, 719),
979+
),
980+
or_byte_string: ThreeArgumentsCosting::new(
981+
ThreeArgumentsCosting::linear_in_max_y_z(0, 1),
982+
ThreeArgumentsCosting::linear_in_y_and_z(100181, 726, 719),
983+
),
984+
xor_byte_string: ThreeArgumentsCosting::new(
985+
ThreeArgumentsCosting::linear_in_max_y_z(0, 1),
986+
ThreeArgumentsCosting::linear_in_y_and_z(100181, 726, 719),
987+
),
988+
complement_byte_string: OneArgumentCosting::new(
989+
OneArgumentCosting::linear_cost(0, 1),
990+
OneArgumentCosting::linear_cost(107878, 680),
991+
),
992+
read_bit: TwoArgumentsCosting::new(
993+
TwoArgumentsCosting::constant_cost(1),
994+
TwoArgumentsCosting::constant_cost(95336),
995+
),
996+
write_bits: ThreeArgumentsCosting::new(
997+
ThreeArgumentsCosting::linear_in_x(0, 1),
998+
ThreeArgumentsCosting::linear_in_y(281145, 18848),
999+
),
1000+
replicate_byte: TwoArgumentsCosting::new(
1001+
TwoArgumentsCosting::linear_in_x(1, 1),
1002+
TwoArgumentsCosting::linear_in_x(180194, 159),
1003+
),
1004+
shift_byte_string: TwoArgumentsCosting::new(
1005+
TwoArgumentsCosting::linear_in_x(0, 1),
1006+
TwoArgumentsCosting::linear_in_x(158519, 8942),
1007+
),
1008+
rotate_byte_string: TwoArgumentsCosting::new(
1009+
TwoArgumentsCosting::linear_in_x(0, 1),
1010+
TwoArgumentsCosting::linear_in_x(159378, 8813),
1011+
),
1012+
count_set_bits: OneArgumentCosting::new(
1013+
OneArgumentCosting::constant_cost(1),
1014+
OneArgumentCosting::linear_cost(107490, 3298),
1015+
),
1016+
find_first_set_bit: OneArgumentCosting::new(
1017+
OneArgumentCosting::constant_cost(1),
1018+
OneArgumentCosting::linear_cost(106057, 655),
1019+
),
1020+
ripemd_160: OneArgumentCosting::new(
1021+
OneArgumentCosting::constant_cost(3),
1022+
OneArgumentCosting::linear_cost(1964219, 24520),
1023+
),
8831024
}
8841025
}
8851026
}

crates/uplc/src/machine/cost_model/costing.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,13 @@ impl Cost<2> for TwoArguments {
204204
pub enum ThreeArguments {
205205
ConstantCost(i64),
206206
// AddedSizes(AddedSizes),
207-
// LinearInX(LinearSize),
207+
LinearInX(LinearSize),
208208
LinearInY(LinearSize),
209209
LinearInZ(LinearSize),
210210
QuadraticInZ(QuadraticFunction),
211211
LiteralInYorLinearInZ(LinearSize),
212+
LinearInYAndZ(TwoVariableLinearSize),
213+
LinearInMaxYZ(LinearSize),
212214
}
213215

214216
pub type ThreeArgumentsCosting = Costing<3, ThreeArguments>;
@@ -237,18 +239,34 @@ impl ThreeArgumentsCosting {
237239
coeff_2,
238240
})
239241
}
242+
243+
pub fn linear_in_y_and_z(intercept: i64, slope1: i64, slope2: i64) -> ThreeArguments {
244+
ThreeArguments::LinearInYAndZ(TwoVariableLinearSize {
245+
intercept,
246+
slope1,
247+
slope2,
248+
})
249+
}
250+
251+
pub fn linear_in_max_y_z(intercept: i64, slope: i64) -> ThreeArguments {
252+
ThreeArguments::LinearInMaxYZ(LinearSize { intercept, slope })
253+
}
254+
255+
pub fn linear_in_x(intercept: i64, slope: i64) -> ThreeArguments {
256+
ThreeArguments::LinearInX(LinearSize { intercept, slope })
257+
}
240258
}
241259

242260
impl Cost<3> for ThreeArguments {
243261
fn cost(&self, args: [i64; 3]) -> i64 {
244-
// let x = args[0];
262+
let x = args[0];
245263
let y = args[1];
246264
let z = args[2];
247265

248266
match self {
249267
ThreeArguments::ConstantCost(c) => *c,
250268
// ThreeArguments::AddedSizes(s) => (x + y + z) * s.slope + s.intercept,
251-
// ThreeArguments::LinearInX(l) => x * l.slope + l.intercept,
269+
ThreeArguments::LinearInX(l) => x * l.slope + l.intercept,
252270
ThreeArguments::LinearInY(l) => y * l.slope + l.intercept,
253271
ThreeArguments::LinearInZ(l) => z * l.slope + l.intercept,
254272
ThreeArguments::QuadraticInZ(q) => q.coeff_0 + (q.coeff_1 * z) + (q.coeff_2 * z * z),
@@ -259,6 +277,8 @@ impl Cost<3> for ThreeArguments {
259277
y
260278
}
261279
}
280+
ThreeArguments::LinearInYAndZ(l) => y * l.slope1 + z * l.slope2 + l.intercept,
281+
ThreeArguments::LinearInMaxYZ(l) => y.max(z) * l.slope + l.intercept,
262282
}
263283
}
264284
}
@@ -290,6 +310,13 @@ pub struct LinearSize {
290310
pub slope: i64,
291311
}
292312

313+
#[derive(Debug, PartialEq)]
314+
pub struct TwoVariableLinearSize {
315+
pub intercept: i64,
316+
pub slope1: i64,
317+
pub slope2: i64,
318+
}
319+
293320
#[derive(Debug, PartialEq)]
294321
pub struct AddedSizes {
295322
pub intercept: i64,

0 commit comments

Comments
 (0)