-
Notifications
You must be signed in to change notification settings - Fork 30
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
feat: initializing conditional stack opcodes #32
Conversation
if (self.stack.items.len == 0) { | ||
return ConditionalStackError.EmptyConditionalStack; | ||
} | ||
_ = self.stack.pop(); |
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 don't you return the value?
Should it be named delete then? Not pop
@okhaimie-dev don't forget to ask for a new review when you are finished pushing your changes |
src/script/cond_stack.zig
Outdated
/// | ||
/// Returns: | ||
/// The popped value (u8) if the stack is not empty | ||
/// ConditionalStackError.EmptyConditionalStack if the stack is empty |
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 know what pop return. You can remove this long comment
src/script/cond_stack.zig
Outdated
/// Push a conditional value onto the stack | ||
/// | ||
/// Args: | ||
/// value: The conditional value to push (typically 0, 1, or 2) |
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.
Can it be something else than 0, 1 or 2? You comment suggest it can
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 can you define an enum for more readability
OpCondFalse = 0
OpCondTrue = 1
OpCondSkip = 2
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.
Can it be something else than 0, 1 or 2? You comment suggest it can
Reading other implementations it looks like it cannot. So please change your comment to not mean that it could
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.
And ofcourse use those OpCond enum in your tests rather than 1, 2, 3
if (self.stack.items.len == 0) { | ||
return ConditionalStackError.UnbalancedConditional; | ||
} | ||
_ = self.stack.pop(); |
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.
Don't you want to return the poped value?
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.
@tdelabro, I don't see any need to pop it is possible to remove the value completely. what do you think?
@@ -391,3 +391,27 @@ pub fn isUnnamedPushNDataOpcode(opcode: Opcode) ?u8 { | |||
const opcodeByte = opcode.toBytes(); | |||
return if (opcodeByte > 0x00 and opcodeByte <= 0x4b) opcodeByte else null; | |||
} | |||
|
|||
/// Conditional execution constants for script operations. | |||
pub const OpConditional = enum(u8) { |
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.
Those are not Opcodes so I don't like the name.
What about "CondStackValue" ?
/// | ||
/// Returns: | ||
/// Possible error if allocation fails | ||
pub fn push(self: *Self, value: u8) !void { |
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.
So if values are strictly limited, change the signature to reflect that:
pub fn push(self: *Self, value: CondStackValue) !void
const Self = @This(); | ||
|
||
/// Dynamic array to store conditional values | ||
stack: std.ArrayList(u8), |
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.
std.ArrayList(CondStackValue) is more restrictive and more expressive
@okhaimie-dev are you still working on this? |
I'll send a fix tomorrow, I have been traveling |
@okhaimie-dev how is it going? |
@tdelabro It's already covered here I didn't notice this but I don't understand what the problem is that is still being faced here to now? |
@KhairallahA there are a few comments I did that have to be fixed |
var engine = Engine.init(allocator, script, ScriptFlags{}); | ||
defer engine.deinit(); | ||
|
||
try engine.stack.pushBool(true); // Push a true value onto the stack |
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 don't think it is necessary to push bool values.
OP_0 = FALSE
OP_1 = TRUE
OP_1 should be the value that returns TRUE and OP_0 should return FALSE.
(According to what is written in the ops implementation, let me know if there is a use case like this, I may be wrong)
|
||
// Test OP_ENDIF with matching OP_IF | ||
{ | ||
const script_bytes = [_]u8{ Opcode.OP_IF.toBytes(), Opcode.OP_ENDIF.toBytes() }; |
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.
You don't need to run opcodes functions directly to test it, you can test OP_ENDIF like this:
const script_bytes = [_]u8{
Opcode.OP_0.toBytes(),
Opcode.OP_IF.toBytes(),
Opcode.OP_1.toBytes(),
Opcode.OP_ENDIF.toBytes(),
};
What we expect:
engine.stack.len() == 0
if (self.stack.items.len == 0) { | ||
return ConditionalStackError.UnbalancedConditional; | ||
} | ||
_ = self.stack.pop(); |
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.
@tdelabro, I don't see any need to pop it is possible to remove the value completely. what do you think?
I think the problem is in understanding the function of Flow control because the complexity in running opcodes execute, not ops themselves https://wiki.bitcoinsv.io/index.php/Opcodes_used_in_Bitcoin_Script#Flow_control @okhaimie-dev, I always think it is better to go through these steps for implementation:
It is possible to implement cond_stack by replacing the use of |
Alright, thanks. Working on this rn |
@okhaimie-dev let me know if there's any problem you face |
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.
How about adding these opcodes in engine file? No need to clutter your mind like that, better have them all in one place.
/// Convert the enum to its underlying u8 value | ||
pub fn toU8(self: OpConditional) u8 { | ||
return @intFromEnum(self); | ||
} | ||
|
||
/// Create an OpConditional from a u8 value | ||
pub fn fromU8(value: u8) !OpConditional { | ||
return std.meta.intToEnum(OpConditional, value) catch { | ||
return error.InvalidOpConditional; | ||
}; | ||
} |
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.
By using the @tdelabro method to include CondStackValue
as a data type as an alternative to u8
, you will not need to use these functions.
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.
@KhairallahA if I don't make a PR in the next 24hrs, you can take over this. I am still trying to get settled and not had enough time to dig into it so far.
cc: @tdelabro
let's close this as the project is put on hold. I will still pay you something for your work on OnlyDust, ping me if I forget |
Implement conditional opcodes and wip to enhance script code structure
Added the following opcodes with corresponding tests:
opIf
opNotIf
opElse
opEndIf
Others
opReserved
opVer
Improvements:
cond_stack
for managing conditional executionThis commit addresses issue #29