Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
5262641
feat(rpc): implement getBlock response types
ajw221 Feb 9, 2026
4e888a3
feat(replay): persist tx status meta and rewards in ledger
ajw221 Feb 9, 2026
11d5914
fix(runtime): manage CPI instruction info lifetimes
ajw221 Feb 9, 2026
673e8d3
feat(rpc): include block time in getBlock and simplify sysvar clock p…
ajw221 Feb 9, 2026
c3059cd
fix(replay): use written pubkey for mint cache keys
ajw221 Feb 9, 2026
3ac72d8
fix(conformance): add explicit type annotation for atomic value
ajw221 Feb 9, 2026
d2aa9ef
feat(rpc): support confirmed commitment in getBlock and improve fallb…
ajw221 Feb 9, 2026
884b235
fix(rpc): read block time from atomic state instead of constants
ajw221 Feb 9, 2026
8b2abcd
feat(rpc): add instruction parsing infrastructure for getBlock
ajw221 Feb 17, 2026
5e362c1
fix(style): clean up long lines and apply consistent formatting
ajw221 Feb 17, 2026
29b54d8
fix(rpc): capitalize reward type enum values for API consistency
ajw221 Feb 17, 2026
555f31f
refactor(rpc): improve type safety and memory management in transacti…
ajw221 Feb 17, 2026
8c1a92f
style: wrap long function calls and conditionals for readability
ajw221 Feb 17, 2026
3d7f605
fix(ledger): use Pubkey directly instead of pointer in rewards benchmark
ajw221 Feb 17, 2026
89c1502
refactor(rpc): use pointer for UiParsedInstruction in union
ajw221 Feb 17, 2026
43733b3
test(rpc): add unit tests for rewards, parse_instruction, and seriali…
ajw221 Feb 17, 2026
2298641
fix(style): format getBlock test function calls
ajw221 Feb 18, 2026
27e1c0d
test(rpc): add comprehensive unit tests for BlockHookContext conversi…
ajw221 Feb 18, 2026
2b4a6c0
test(runtime): add comprehensive unit tests for transaction status, c…
ajw221 Feb 18, 2026
f5a2c13
refactor(rpc): improve getBlock transaction encoding structure
ajw221 Feb 18, 2026
9796d1d
refactor(rpc): make rewards field optional in transaction status meta
ajw221 Feb 18, 2026
0e0ecda
refactor(rpc): simplify block metadata storage and rewards handling
ajw221 Feb 19, 2026
895602f
fix(replay): correct schema path for blocktime and block_height
ajw221 Feb 19, 2026
47d0634
fix(conformance): handle unused return value from updateClock
ajw221 Feb 19, 2026
e8ca7e1
feat(rpc): add jsonParsed encoding support for getBlock transactions
ajw221 Feb 20, 2026
85de0f6
refactor(rewards): simplify RewardInfo struct
ajw221 Feb 20, 2026
c8c7fcc
feat(rpc): add accounts transactionDetails support for getBlock
ajw221 Feb 20, 2026
189463a
fix(style): break long lines
ajw221 Feb 21, 2026
e67b06e
test(rpc): add tests for getBlock encoding and serialization
ajw221 Feb 23, 2026
c0d1c6a
refactor(rpc): reorganize transaction encoding for getBlock
ajw221 Feb 23, 2026
844248d
fix(rpc): use defer instead of errdefer for cleanup in message encoding
ajw221 Feb 23, 2026
36d7b47
fix(rpc): use ReservedAccountKeys alias consistently
ajw221 Feb 23, 2026
a3c98e0
fix(core): use constSlice for Hash JSON serialization
ajw221 Feb 23, 2026
7a4af0b
chore(rpc): remove redundant comments in transaction encoding
ajw221 Feb 23, 2026
f5771c4
fix(ledger): make TransactionWithStatusMeta public
ajw221 Feb 23, 2026
ef19353
refactor(ledger): batch writes in writeTransactionStatus and accept s…
ajw221 Feb 24, 2026
87cd480
fix(rpc): use rooted block for confirmed slots at or below latest con…
ajw221 Feb 24, 2026
7dc731c
feat(rpc): support encoding-only parameter for getBlock
ajw221 Feb 24, 2026
f262d45
refactor: migrate to updated std library APIs
ajw221 Feb 25, 2026
6787a5c
fix(ledger): add errdefer for owned_loaded_addresses allocation
ajw221 Feb 25, 2026
66020d6
docs(ledger): add agave reference for empty transaction rewards
ajw221 Feb 25, 2026
60fb2c2
style(rpc): remove unused import and fix long line formatting
ajw221 Feb 25, 2026
f09548e
refactor(rpc): use inline loop for ParsableProgram.fromID lookup
ajw221 Feb 25, 2026
5755906
refactor(replay): use ArrayListUnmanaged for transaction key lists
ajw221 Feb 25, 2026
47b0463
fix(replay): populate loaded addresses from address lookup tables
ajw221 Feb 26, 2026
503501f
feat(replay): record epoch rewards and num_partitions to blockstore
ajw221 Feb 26, 2026
a428788
fix(ledger): properly deinit nested allocations in TransactionStatusMeta
ajw221 Feb 26, 2026
ca60af3
fix(rpc): serialize float uiAmount to match serde_json output
ajw221 Feb 26, 2026
1890b73
fix(ledger): properly deinit nested allocations in TransactionStatusMeta
ajw221 Feb 26, 2026
0e818f7
fix: add errdefer and simplify allocations in ledger, rpc, and system…
ajw221 Feb 27, 2026
5c365f1
fix(runtime): propagate OOM from resolveTokenBalances and enable secp…
ajw221 Feb 27, 2026
21eb2f6
style(rpc): replace @This() with explicit type names in jsonStringify…
ajw221 Feb 27, 2026
b9f8a80
refactor(rpc): replace ReservedAccountKeys with core ReservedAccounts
ajw221 Feb 27, 2026
a2bd396
docs(ledger): clarify extractLogMessages ownership semantics
ajw221 Feb 27, 2026
3954464
refactor(rpc): delete LoadedMessage, use Message.isWritable directly
ajw221 Mar 2, 2026
577a404
refactor(rpc): rename BlockHookContext to LedgerHookContext
ajw221 Mar 2, 2026
b37c0b3
refactor(rpc): extract LedgerHookContext into its own module
ajw221 Mar 2, 2026
93d9cbc
style: standardize test names and clean up code organization
ajw221 Mar 2, 2026
f403e13
feat(rpc): implement SPL Token extension sub-instruction parsing
ajw221 Mar 2, 2026
6d7b2a4
refactor(rpc): rename allocator to arena and remove redundant errdefers
ajw221 Mar 2, 2026
31570c7
style(rpc): wrap long lines in token extension parsers
ajw221 Mar 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions conformance/src/txn_execute.zig
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ fn executeTxnContext(
.update_sysvar_deps = update_sysvar_deps,
},
);
try update_sysvar.updateClock(allocator, .{
_ = try update_sysvar.updateClock(allocator, .{
.feature_set = &feature_set,
.epoch_schedule = &epoch_schedule,
.epoch_stakes = epoch_stakes_map.getPtr(epoch),
Expand Down Expand Up @@ -611,7 +611,7 @@ fn executeTxnContext(
.update_sysvar_deps = update_sysvar_deps,
},
);
try update_sysvar.updateClock(allocator, .{
_ = try update_sysvar.updateClock(allocator, .{
.feature_set = &feature_set,
.epoch_schedule = &epoch_schedule,
.epoch_stakes = epoch_stakes_map.getPtr(epoch),
Expand Down
5 changes: 5 additions & 0 deletions src/cmd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,11 @@ fn validator(
.account_reader = account_store.reader(),
});

try app_base.rpc_hooks.set(allocator, sig.rpc.hook_contexts.Ledger{
.ledger = &ledger,
.slot_tracker = &replay_service_state.replay_state.slot_tracker,
});

const replay_thread = try replay_service_state.spawnService(
&app_base,
if (maybe_vote_sockets) |*vs| vs else null,
Expand Down
11 changes: 10 additions & 1 deletion src/core/ReservedAccounts.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,19 @@ pub fn initForSlot(
slot: Slot,
) Allocator.Error!ReservedAccounts {
var reserved_accounts = try init(allocator);
errdefer reserved_accounts.deinit(allocator);
reserved_accounts.update(feature_set, slot);
return reserved_accounts;
}

pub fn initAllActivated(allocator: Allocator) Allocator.Error!ReservedAccounts {
var reserved_accounts = ReservedAccounts{ .map = .empty };
errdefer reserved_accounts.deinit(allocator);
try reserved_accounts.map.ensureTotalCapacity(allocator, ACCOUNTS.len);
for (ACCOUNTS) |account| reserved_accounts.map.putAssumeCapacity(account.pubkey, {});
return reserved_accounts;
}

pub fn update(
self: *ReservedAccounts,
feature_set: *const FeatureSet,
Expand All @@ -55,7 +64,7 @@ pub fn update(
}
}

const ACCOUNTS: []const struct { pubkey: Pubkey, feature: ?Feature } = &.{
const ACCOUNTS = [_]struct { pubkey: Pubkey, feature: ?Feature }{
// zig fmt: off
.{ .pubkey = sig.runtime.program.address_lookup_table.ID, .feature = .add_new_reserved_account_keys },
.{ .pubkey = sig.runtime.program.bpf_loader.v1.ID, .feature = null },
Expand Down
1 change: 1 addition & 0 deletions src/core/features.zon
Original file line number Diff line number Diff line change
Expand Up @@ -253,4 +253,5 @@
.{ .name = "increase_cpi_account_info_limit", .pubkey = "H6iVbVaDZgDphcPbcZwc5LoznMPWQfnJ1AM7L1xzqvt5" },
.{ .name = "vote_state_v4", .pubkey = "Gx4XFcrVMt4HUvPzTpTSVkdDVgcDSjKhDN1RqRS6KDuZ" },
.{ .name = "enable_bls12_381_syscall", .pubkey = "b1sraWPVFdcUizB2LV5wQTeMuK8M313bi5bHjco5eVU" },
.{ .name = "remove_simple_vote_from_cost_model", .pubkey = "2GCrNXbzmt4xrwdcKS2RdsLzsgu4V5zHAemW57pcHT6a" },
}
4 changes: 4 additions & 0 deletions src/core/hash.zig
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ pub const Hash = extern struct {
};
}

pub fn jsonStringify(self: Hash, write_stream: anytype) !void {
try write_stream.write(self.base58String().constSlice());
}

/// Intended to be used in tests.
pub fn initRandom(random: std.Random) Hash {
var data: [SIZE]u8 = undefined;
Expand Down
6 changes: 5 additions & 1 deletion src/core/transaction.zig
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,13 @@ pub const Message = struct {
pub fn isWritable(
self: Message,
index: usize,
lookups: LookupTableAccounts,
maybe_lookups: ?LookupTableAccounts,
reserved_accounts: *const ReservedAccounts,
) bool {
const lookups = maybe_lookups orelse LookupTableAccounts{
.writable = &.{},
.readonly = &.{},
};
const pubkey = blk: {
if (index < self.account_keys.len) {
if (index >= self.signature_count) {
Expand Down
16 changes: 16 additions & 0 deletions src/ledger/Ledger.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const std = @import("std");
const builtin = @import("builtin");
const sig = @import("../sig.zig");
const lib = @import("lib.zig");

Expand Down Expand Up @@ -53,6 +54,21 @@ pub fn init(
};
}

pub fn initForTest(
allocator: Allocator,
) !struct { Ledger, std.testing.TmpDir } {
if (!builtin.is_test) @compileError("only used in tests");
var tmp = std.testing.tmpDir(.{});
try tmp.dir.makeDir("ledger");
const path = try tmp.dir.realpathAlloc(allocator, "ledger");
defer allocator.free(path);

return .{
try Ledger.init(allocator, .FOR_TESTS, path, null),
tmp,
};
}

pub fn reader(self: *Ledger) Reader {
return .{
.ledger = self,
Expand Down
5 changes: 3 additions & 2 deletions src/ledger/Reader.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1519,7 +1519,6 @@ pub const VersionedConfirmedBlock = struct {

pub fn deinit(self: @This(), allocator: Allocator) void {
for (self.transactions) |it| it.deinit(allocator);
for (self.rewards) |it| it.deinit(allocator);
allocator.free(self.transactions);
allocator.free(self.rewards);
}
Expand Down Expand Up @@ -1548,7 +1547,7 @@ const ConfirmedTransactionWithStatusMeta = struct {
block_time: ?UnixTimestamp,
};

const TransactionWithStatusMeta = union(enum) {
pub const TransactionWithStatusMeta = union(enum) {
// Very old transactions may be missing metadata
missing_metadata: Transaction,
// Versioned stored transaction always have metadata
Expand Down Expand Up @@ -2498,6 +2497,7 @@ test getTransactionStatus {
.loaded_addresses = .{},
.return_data = .{},
.compute_units_consumed = 1000,
.cost_units = null,
};

// insert transaction status and root it
Expand Down Expand Up @@ -2689,6 +2689,7 @@ test getConfirmedSignaturesForAddress {
.loaded_addresses = .{},
.return_data = .{},
.compute_units_consumed = 1000,
.cost_units = null,
};
try write_batch.put(schema.transaction_status, .{ sig1, slot }, status_meta);

Expand Down
15 changes: 10 additions & 5 deletions src/ledger/ResultWriter.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ pub fn writeTransactionStatus(
self: *const ResultWriter,
slot: Slot,
signature: Signature,
writeable_keys: ArrayList(Pubkey),
readonly_keys: ArrayList(Pubkey),
writeable_keys: []const Pubkey,
readonly_keys: []const Pubkey,
status: TransactionStatusMeta,
transaction_index: usize,
) !void {
try self.ledger.db.put(schema.transaction_status, .{ signature, slot }, status);
var write_batch = try self.ledger.db.initWriteBatch();
defer write_batch.deinit();

try write_batch.put(schema.transaction_status, .{ signature, slot }, status);
inline for (.{ writeable_keys, readonly_keys }, .{ true, false }) |keys, writeable| {
for (keys.items) |address| {
try self.ledger.db.put(
for (keys) |address| {
try write_batch.put(
schema.address_signatures,
.{
.address = address,
Expand All @@ -57,6 +60,8 @@ pub fn writeTransactionStatus(
);
}
}

try self.ledger.db.commit(&write_batch);
}

/// agave: insert_bank_hash
Expand Down
10 changes: 5 additions & 5 deletions src/ledger/benchmarks.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn createRewards(allocator: std.mem.Allocator, count: usize) !Rewards {
var rewards: Rewards = Rewards.init(allocator);
for (0..count) |i| {
try rewards.append(Reward{
.pubkey = &Pubkey.initRandom(rand).data,
.pubkey = Pubkey.initRandom(rand),
.lamports = @intCast(42 + i),
.post_balance = std.math.maxInt(u64),
.reward_type = RewardType.fee,
Expand Down Expand Up @@ -160,7 +160,7 @@ pub const BenchmarkLedger = struct {
var indices = try std.array_list.Managed(u32).initCapacity(allocator, num_reads);
defer indices.deinit();
for (0..num_reads) |_| {
indices.appendAssumeCapacity(rng.random().uintAtMost(u32, @intCast(total_shreds)));
indices.appendAssumeCapacity(rng.random().uintAtMost(u32, @intCast(total_shreds - 1)));
}

const reader = state.reader();
Expand Down Expand Up @@ -247,7 +247,7 @@ pub const BenchmarkLedger = struct {
var indices = try std.array_list.Managed(u32).initCapacity(allocator, total_shreds);
defer indices.deinit();
for (0..total_shreds) |_| {
indices.appendAssumeCapacity(rng.random().uintAtMost(u32, @intCast(total_shreds)));
indices.appendAssumeCapacity(rng.random().uintAtMost(u32, @intCast(total_shreds - 1)));
}

const reader = state.reader();
Expand Down Expand Up @@ -347,8 +347,8 @@ pub const BenchmarkLedger = struct {
_ = try result_writer.writeTransactionStatus(
slot,
signature,
w_keys,
r_keys,
w_keys.items,
r_keys.items,
status,
tx_idx,
);
Expand Down
2 changes: 2 additions & 0 deletions src/ledger/tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ pub fn insertDataForBlockTest(
.loaded_addresses = .{},
.return_data = .{},
.compute_units_consumed = compute_units_consumed,
.cost_units = null,
};
try db.put(schema.transaction_status, .{ signature, slot }, status);
try db.put(schema.transaction_status, .{ signature, slot + 1 }, status);
Expand All @@ -435,6 +436,7 @@ pub fn insertDataForBlockTest(
.loaded_addresses = .{},
.return_data = .{},
.compute_units_consumed = compute_units_consumed,
.cost_units = null,
},
});
}
Expand Down
Loading