Skip to content
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

OP_TOALTSTACK OP_FROMALTSTACK opcodes #105

Merged
merged 12 commits into from
Sep 23, 2024
36 changes: 36 additions & 0 deletions src/script/engine.zig
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ pub const Engine = struct {
Opcode.OP_NOP => try self.opNop(),
Opcode.OP_VERIFY => try self.opVerify(),
Opcode.OP_RETURN => try self.opReturn(),
Opcode.OP_TOALTSTACK => try self.opToAltStack(),
Opcode.OP_FROMALTSTACK => try self.opFromAltStack(),
Opcode.OP_2DROP => try self.op2Drop(),
Opcode.OP_2DUP => try self.op2Dup(),
Opcode.OP_3DUP => try self.op3Dup(),
Expand Down Expand Up @@ -269,6 +271,18 @@ pub const Engine = struct {
return error.EarlyReturn;
}

/// OP_TOALTSTACK: Puts the value onto the top of the alt stack, and removes it from the main stack.
fn opToAltStack(self: *Engine) EngineError!void {
const value = try self.stack.pop();
try self.alt_stack.pushElement(value);
}

/// OP_FROMALTSTACK: Puts the value onto the top of the main stack, and removes it from the alt stack.
fn opFromAltStack(self: *Engine) EngineError!void {
const value = try self.alt_stack.pop();
try self.stack.pushElement(value);
}

/// OP_2DROP: Drops top 2 stack items
fn op2Drop(self: *Engine) !void {
const first = try self.stack.pop();
Expand Down Expand Up @@ -527,6 +541,28 @@ test "Script execution - OP_RETURN" {
}
}

test "Script execution - OP_TOALTSTACK OP_FROMALTSTACK" {
const allocator = std.testing.allocator;

// Simple script: OP_1 OP_TOALTSTACK OP_FROMALTSTACK
const script_bytes = [_]u8{
Opcode.OP_1.toBytes(),
Opcode.OP_2.toBytes(),
Opcode.OP_TOALTSTACK.toBytes(),
Opcode.OP_TOALTSTACK.toBytes(),
Opcode.OP_FROMALTSTACK.toBytes(),
};
const script = Script.init(&script_bytes);

var engine = Engine.init(allocator, script, .{});
defer engine.deinit();

try engine.execute();

try std.testing.expectEqual(1, try engine.stack.peekInt(0));
try std.testing.expectEqual(2, try engine.alt_stack.peekInt(0));
}

test "Script execution - OP_1 OP_1 OP_1 OP_2Drop" {
const allocator = std.testing.allocator;

Expand Down
Loading