Skip to content

Commit 5a63bb1

Browse files
authored
Merge pull request #191 from iotaledger/feat/correction-records
feat: setup correction records
2 parents 1f2e81f + 2ee0843 commit 5a63bb1

File tree

4 files changed

+83
-8
lines changed

4 files changed

+83
-8
lines changed

audit-trail-move/Move.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ dependencies = [
4242
]
4343

4444
[move.toolchain-version]
45-
compiler-version = "1.14.1-rc"
45+
compiler-version = "1.15.0"
4646
edition = "2024.beta"
4747
flavor = "iota"

audit-trail-move/sources/audit_trail.move

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use audit_trail::{
1212
locking::{Self, LockingConfig, LockingWindow, set_delete_record_lock},
1313
permission::{Self, Permission},
1414
record::{Self, Record},
15+
record_correction,
1516
role_map::{Self, RoleMap}
1617
};
1718
use iota::{clock::{Self, Clock}, event, linked_table::{Self, LinkedTable}};
@@ -155,6 +156,7 @@ public fun create<D: store + copy>(
155156
0,
156157
creator,
157158
timestamp,
159+
record_correction::new(),
158160
);
159161

160162
linked_table::push_back(&mut records, 0, record);
@@ -278,6 +280,7 @@ public fun add_record<D: store + copy>(
278280
seq,
279281
caller,
280282
timestamp,
283+
record_correction::new(),
281284
);
282285

283286
linked_table::push_back(&mut trail.records, seq, record);

audit-trail-move/sources/record.move

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33

44
/// Record module for audit trail entries
55
///
6-
/// A Record represents a single entry in an audit trail, stored in a LinkedTable
7-
/// and addressed by trail_id + sequence_number.
6+
/// A Record represents a single entry in an audit trail, stored in a
7+
/// LinkedTable and addressed by trail_id + sequence_number.
88
module audit_trail::record;
99

10+
use audit_trail::record_correction::RecordCorrection;
1011
use std::string::String;
1112

12-
/// A single record in the audit trail (stored in LinkedTable, no ObjectID)
13+
/// A single record in the audit trail
1314
public struct Record<D: store + copy> has store {
1415
/// Arbitrary data stored on-chain
1516
stored_data: D,
@@ -21,24 +22,28 @@ public struct Record<D: store + copy> has store {
2122
added_by: address,
2223
/// When this record was added (milliseconds)
2324
added_at: u64,
25+
/// Correction tracker for this record
26+
correction: RecordCorrection,
2427
}
2528

2629
// ===== Constructors =====
2730

28-
/// Create a new record (package-private, called by audit_trails module)
31+
/// Create a new record
2932
public(package) fun new<D: store + copy>(
3033
stored_data: D,
3134
record_metadata: Option<String>,
3235
sequence_number: u64,
3336
added_by: address,
3437
added_at: u64,
38+
correction: RecordCorrection,
3539
): Record<D> {
3640
Record {
3741
stored_data,
3842
record_metadata,
3943
sequence_number,
4044
added_by,
4145
added_at,
46+
correction,
4247
}
4348
}
4449

@@ -69,16 +74,19 @@ public fun added_at<D: store + copy>(record: &Record<D>): u64 {
6974
record.added_at
7075
}
7176

72-
// ===== Destructors =====
77+
/// Get the correction tracker for this record
78+
public fun correction<D: store + copy>(record: &Record<D>): &RecordCorrection {
79+
&record.correction
80+
}
7381

74-
/// Destroy a record (package-private, called by audit_trail module when deleting)
75-
/// Note: D must have `drop` ability to allow deletion
82+
/// Destroy a record
7683
public(package) fun destroy<D: store + copy + drop>(record: Record<D>) {
7784
let Record {
7885
stored_data: _,
7986
record_metadata: _,
8087
sequence_number: _,
8188
added_by: _,
8289
added_at: _,
90+
correction: _,
8391
} = record;
8492
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (c) 2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
/// Module for tracking correction relationships for a record
5+
module audit_trail::record_correction;
6+
7+
use iota::vec_set::{Self, VecSet};
8+
9+
/// Bidirectional correction tracking for audit records
10+
public struct RecordCorrection has copy, drop, store {
11+
replaces: VecSet<u64>,
12+
is_replaced_by: Option<u64>,
13+
}
14+
15+
/// Create a new correction tracker for a normal (non-correcting) record
16+
public fun new(): RecordCorrection {
17+
RecordCorrection {
18+
replaces: vec_set::empty(),
19+
is_replaced_by: option::none(),
20+
}
21+
}
22+
23+
/// Create a correction tracker for a correcting record
24+
public fun with_replaces(replaced_seq_nums: VecSet<u64>): RecordCorrection {
25+
RecordCorrection {
26+
replaces: replaced_seq_nums,
27+
is_replaced_by: option::none(),
28+
}
29+
}
30+
31+
/// Get the set of sequence numbers this record replaces
32+
public fun replaces(correction: &RecordCorrection): &VecSet<u64> {
33+
&correction.replaces
34+
}
35+
36+
/// Get the sequence number of the record that replaced this one
37+
public fun is_replaced_by(correction: &RecordCorrection): Option<u64> {
38+
correction.is_replaced_by
39+
}
40+
41+
/// Check if this record is a correction (replaces other records)
42+
public fun is_correction(correction: &RecordCorrection): bool {
43+
!vec_set::is_empty(&correction.replaces)
44+
}
45+
46+
/// Check if this record has been replaced by another record
47+
public fun is_replaced(correction: &RecordCorrection): bool {
48+
correction.is_replaced_by.is_some()
49+
}
50+
51+
/// Set the sequence number of the record that replaced this one
52+
public(package) fun set_replaced_by(correction: &mut RecordCorrection, replacement_seq: u64) {
53+
correction.is_replaced_by = option::some(replacement_seq);
54+
}
55+
56+
/// Add a sequence number to the set of records this record replaces
57+
public(package) fun add_replaces(correction: &mut RecordCorrection, seq_num: u64) {
58+
correction.replaces.insert(seq_num);
59+
}
60+
61+
/// Destroy a RecordCorrection
62+
public(package) fun destroy(correction: RecordCorrection) {
63+
let RecordCorrection { replaces: _, is_replaced_by: _ } = correction;
64+
}

0 commit comments

Comments
 (0)