-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support hint function #220
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR lgtm, I have a few questions wrt the type transformations.
} | ||
} | ||
|
||
pub fn new_constant_typ<F: BackendField>(cst_info: &ConstInfo<F>, span: Span) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is the coding style :D
ErrorKind::InvalidFnCall("only hint functions allowed"), | ||
expr.span, | ||
)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw what is the rationale here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, solves my previous comment :D. I guess here we check that a hint can call only another hint which makes sense
The hint functions shouldn’t be allowed to call constrained functions,
right? Otherwise it will end up some constraints created as an orphan
circuit.
…On Tue, Nov 12, 2024 at 6:27 PM David Wong ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/circuit_writer/ir.rs
<#220 (comment)>:
> @@ -660,6 +660,14 @@ impl<B: Backend> IRWriter<B> {
FnKind::Native(func) => {
// module::fn_name(args)
// ^^^^^^
+ // only allow calling hint functions
+ if !func.is_hint {
+ return Err(self.error(
+ ErrorKind::InvalidFnCall("only hint functions allowed"),
+ expr.span,
+ ));
+ }
btw what is the rationale here?
—
Reply to this email directly, view it on GitHub
<#220 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAMDRGFA5FYBQJ7IHHRNZB32AHQZXAVCNFSM6AAAAABRDW6KYSVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDIMRZGMZDMMBVGE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
you could think that constraint functions wouldn't produce constraints if called by hints, but yeah I don't think it's a big deal :o was just wondering |
LGTM but @StefanosChaliasos I'll let you approve |
@@ -0,0 +1,1119 @@ | |||
use ark_ff::Zero; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw as most of this file will be useful in the future to have an IR pass, I think it should be moved to an circ_ir folder or something, and moved out of the circuit_writer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approving for the sake of getting this moved, let's add a disclaimer that we're still experimental in the README
@@ -199,6 +202,48 @@ pub trait Backend: Clone { | |||
|
|||
Ok(res) | |||
} | |||
Value::HintIR(t, named_vars) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This lgtm, but I would suggest adding some unit tests here to check corner cases (0, p, p-1, p+1).
@@ -0,0 +1,1119 @@ | |||
use ark_ff::Zero; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree
if idx < self.cvars.len() { | ||
Some(&self.cvars[idx]) | ||
} else { | ||
None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you handle that? Should throw an error here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be cleaner instead of an option to return an error here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it is currently handled by callers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should add an issue to change that? Or do you think it's better to handle that in the callers? In any case even if you return a result it will be basically handled by callers but it would be more explicit and it will probably print a nicer error message?
.as_value_opt() | ||
.map(|v| BigUint::from(v.as_pf().i().to_u64_wrapping())) | ||
} else { | ||
None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly here
body, | ||
} => { | ||
match argument { | ||
ForLoopArgument::Range(range) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the range supposed to be known at compile time? No, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it should be known at compiler time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that? I guess when we are in a hint, there isn't any reason why this should be known at compile time as we are out-of-circuit, right? Do I miss something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh yeah, this is a good point. I created an issue for that: #234
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh wait, I misunderstood your question.
so yeah, this is an interesting insight. It should allow variables as the range.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess lets keep this way for now, and will revisit this when someone raises the scenarios they need the range to be variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't do TDD here, we do user-complaint driven development
.expect("expected constant") | ||
.into(); | ||
let start: u32 = start_bg.try_into().map_err(|_| { | ||
self.error(ErrorKind::InvalidRangeSize, range.start.span) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have this error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
atm, the size of the number is restricted to u32, so it throws error if it is bigger.
function: &FunctionDef, | ||
args: Vec<crate::circuit_writer::fn_env::VarInfo<B::Field, B::Var>>, | ||
) -> Result<Vec<crate::var::Value<B>>> { | ||
assert!(!function.is_main()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually check that we are calling a hint function and not a non hint one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, a hint should only be able to call hint function, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, only hint functions are allowed.
ErrorKind::InvalidFnCall("only hint functions allowed"), | ||
expr.span, | ||
)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, solves my previous comment :D. I guess here we check that a hint can call only another hint which makes sense
This is a POC to support native hint function based on circ's IR and API.
The integration is quite straightforward. The major changes are listed below. Most of the code in
circuit_writer/ir.rs
remain the same as the circuit synthesizer:circ IR can be composed using its
term
API, which can be used independently. (doesn't have to couple with other parts in circ)creates a IR translator based on the template of synthesizer, to translate the mast to IR if it is a hint function.
one major change is to replace the
ConstOrCell
in theVar
with the circ IR term, as a term can represent either constant field or a variable.eg:
So we may want to consider refactor the
var::Var
to cover bothConstOrCell
andTerm
, in order to avoid the code duplication in their.rs
.eg:
atm, everything is defined as field type at low level using the circ IR
create a
Value::HintIR
to represent an IR generated from a hint function, and compute it viacompute_val
using circ's PreComp API.TODOs: