33import java .lang .foreign .*;
44
55import static org .bitcoinkernel .BitcoinKernelBindings .*;
6+ import static org .bitcoinkernel .Transactions .*;
67
78public class Blocks {
89
9- //todo!
10+ // ===== Block Validation State =====
1011 public static class BlockValidationState {
12+ private final MemorySegment inner ;
13+
14+ public enum ValidationMode {
15+ VALID (0 ),
16+ INVALID (1 ),
17+ INTERNAL_ERROR (2 );
18+
19+ private final byte value ;
20+
21+ ValidationMode (int value ) {
22+ this .value = (byte ) value ;
23+ }
24+
25+ public byte getValue () {
26+ return value ;
27+ }
28+
29+ public static ValidationMode fromByte (byte value ) {
30+ for (ValidationMode mode : values ()) {
31+ if (mode .value == value ) {
32+ return mode ;
33+ }
34+ }
35+ throw new IllegalArgumentException ("Invalid Validation Mode: " + value );
36+ }
37+ }
38+
39+ public enum BlockValidationResult {
40+ UNSET (0 ),
41+ CONSENSUS (1 ),
42+ CACHED_INVALID (2 ),
43+ INVALID_HEADER (3 ),
44+ MUTATED (4 ),
45+ MISSING_PREV (5 ),
46+ INVALID_PREV (6 ),
47+ TIME_FUTURE (7 ),
48+ HEADER_LOW_WORK (8 );
49+
50+ private final int value ;
51+
52+ BlockValidationResult (int value ) {
53+ this .value = value ;
54+ }
55+
56+ public int getValue () {
57+ return value ;
58+ }
1159
60+ public static BlockValidationResult fromInt (int value ) {
61+ for (BlockValidationResult result : values ()) {
62+ if (result .value == value ) {
63+ return result ;
64+ }
65+ }
66+ throw new IllegalArgumentException ("Invalid BlockValidationResult: " + value );
67+ }
68+ }
69+
70+ BlockValidationState (MemorySegment inner ) {
71+ if (inner == MemorySegment .NULL ) {
72+ throw new IllegalArgumentException ("Block Validation State cannot be null" );
73+ }
74+ this .inner = inner ;
75+ }
76+
77+ /**
78+ * Get the validation mode indicating whether the block is valid, invalid,
79+ * or an error occurred during validation.
80+ *
81+ * @return The validation mode
82+ */
83+ public ValidationMode getValidationMode () {
84+ byte mode = btck_block_validation_state_get_validation_mode (inner );
85+ return ValidationMode .fromByte (mode );
86+ }
87+
88+ /**
89+ * Get the specific reason why a block was invalid (if applicable).
90+ * Only meaningful when ValidationMode is INVALID.
91+ *
92+ * @return The block validation result
93+ */
94+ public BlockValidationResult getBlockValidationResult () {
95+ int result = btck_block_validation_state_get_block_validation_result (inner );
96+ return BlockValidationResult .fromInt (result );
97+ }
98+
99+ /**
100+ * Check if the block is valid.
101+ *
102+ * @return true if ValidationMode is VALID, false otherwise
103+ */
104+ public boolean isValid () {
105+ return getValidationMode () == ValidationMode .VALID ;
106+ }
107+
108+ /**
109+ * Check if the block is invalid.
110+ *
111+ * @return true if ValidationMode is INVALID, false otherwise
112+ */
113+ public boolean isInvalid () {
114+ return getValidationMode () == ValidationMode .INVALID ;
115+ }
116+
117+ /**
118+ * Check if there was an error during validation
119+ *
120+ * @return true if ValidationMode is INTERNAL_ERROR, false otherwise
121+ */
122+ public boolean hasError () {
123+ return getValidationMode () == ValidationMode .INTERNAL_ERROR ;
124+ }
125+
126+ /**
127+ * Get a human readable description of the validation state
128+ *
129+ * @return A string describing the validation state
130+ */
131+ public String getDescription () {
132+ ValidationMode mode = getValidationMode ();
133+ if (mode == ValidationMode .VALID ) {
134+ return "Block is Valid" ;
135+ } else if (mode == ValidationMode .INVALID ) {
136+ BlockValidationResult result = getBlockValidationResult ();
137+ return "Block is Invalid: " + result .name ();
138+ } else {
139+ return "Internal error during validation" ;
140+ }
141+ }
142+
143+ @ Override
144+ public String toString () {
145+ return String .format ("BlockValidationState{mode=%s, result=%s}" ,
146+ getValidationMode (),
147+ getBlockValidationResult ());
148+ }
149+
150+ MemorySegment getInner () {
151+ return inner ;
152+ }
12153 }
13154
14155 // ===== Block Hash =====
@@ -83,9 +224,37 @@ public void close() throws Exception {
83224 }
84225 }
85226
86- //todo!
227+ // ===== Block Tree Entry =====
87228 public static class BlockTreeEntry {
229+ private final MemorySegment inner ;
230+
231+ BlockTreeEntry (MemorySegment inner ) {
232+ if (inner == MemorySegment .NULL ) {
233+ throw new IllegalArgumentException ("Block Tree cannot be null!" );
234+ }
235+ this .inner = inner ;
236+ }
237+
238+ public BlockTreeEntry getPrevious () {
239+ MemorySegment prev = btck_block_tree_entry_get_previous (inner );
240+ if (prev == MemorySegment .NULL ) {
241+ return null ;
242+ }
243+ return new BlockTreeEntry (prev );
244+ }
245+
246+ public int getHeight () {
247+ return btck_block_tree_entry_get_height (inner );
248+ }
88249
250+ public BlockHash getBlockHash () {
251+ MemorySegment hashPtr = btck_block_tree_entry_get_block_hash (inner );
252+ return new BlockHash (hashPtr );
253+ }
254+
255+ MemorySegment getInner () {
256+ return inner ;
257+ }
89258 }
90259
91260 //todo!
@@ -98,8 +267,10 @@ public void close() throws Exception {
98267 }
99268 }
100269
101- //todo!
270+ // ===== Block Spent Outputs =====
102271 public static class BlockSpentOutputs implements AutoCloseable {
272+ private final MemorySegment inner ;
273+
103274
104275
105276 @ Override
0 commit comments