ord/index/
entry.rs

1use super::*;
2
3pub trait Entry: Sized {
4  type Value;
5
6  fn load(value: Self::Value) -> Self;
7
8  fn store(self) -> Self::Value;
9}
10
11pub type HeaderValue = [u8; 80];
12
13impl Entry for Header {
14  type Value = HeaderValue;
15
16  fn load(value: Self::Value) -> Self {
17    consensus::encode::deserialize(&value).unwrap()
18  }
19
20  fn store(self) -> Self::Value {
21    let mut buffer = Cursor::new([0; 80]);
22    let len = self
23      .consensus_encode(&mut buffer)
24      .expect("in-memory writers don't error");
25    let buffer = buffer.into_inner();
26    debug_assert_eq!(len, buffer.len());
27    buffer
28  }
29}
30
31impl Entry for Rune {
32  type Value = u128;
33
34  fn load(value: Self::Value) -> Self {
35    Self(value)
36  }
37
38  fn store(self) -> Self::Value {
39    self.0
40  }
41}
42
43#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
44pub struct RuneEntry {
45  pub block: u64,
46  pub burned: u128,
47  pub divisibility: u8,
48  pub etching: Txid,
49  pub mints: u128,
50  pub number: u64,
51  pub premine: u128,
52  pub spaced_rune: SpacedRune,
53  pub symbol: Option<char>,
54  pub terms: Option<Terms>,
55  pub timestamp: u64,
56  pub turbo: bool,
57}
58
59impl RuneEntry {
60  pub fn mintable(&self, height: u64) -> Result<u128, MintError> {
61    let Some(terms) = self.terms else {
62      return Err(MintError::Unmintable);
63    };
64
65    if let Some(start) = self.start() {
66      if height < start {
67        return Err(MintError::Start(start));
68      }
69    }
70
71    if let Some(end) = self.end() {
72      if height >= end {
73        return Err(MintError::End(end));
74      }
75    }
76
77    let cap = terms.cap.unwrap_or_default();
78
79    if self.mints >= cap {
80      return Err(MintError::Cap(cap));
81    }
82
83    Ok(terms.amount.unwrap_or_default())
84  }
85
86  pub fn supply(&self) -> u128 {
87    self.premine
88      + self.mints
89        * self
90          .terms
91          .and_then(|terms| terms.amount)
92          .unwrap_or_default()
93  }
94
95  pub fn pile(&self, amount: u128) -> Pile {
96    Pile {
97      amount,
98      divisibility: self.divisibility,
99      symbol: self.symbol,
100    }
101  }
102
103  pub fn start(&self) -> Option<u64> {
104    let terms = self.terms?;
105
106    let relative = terms
107      .offset
108      .0
109      .map(|offset| self.block.saturating_add(offset));
110
111    let absolute = terms.height.0;
112
113    relative
114      .zip(absolute)
115      .map(|(relative, absolute)| relative.max(absolute))
116      .or(relative)
117      .or(absolute)
118  }
119
120  pub fn end(&self) -> Option<u64> {
121    let terms = self.terms?;
122
123    let relative = terms
124      .offset
125      .1
126      .map(|offset| self.block.saturating_add(offset));
127
128    let absolute = terms.height.1;
129
130    relative
131      .zip(absolute)
132      .map(|(relative, absolute)| relative.min(absolute))
133      .or(relative)
134      .or(absolute)
135  }
136}
137
138type TermsEntryValue = (
139  Option<u128>,               // cap
140  (Option<u64>, Option<u64>), // height
141  Option<u128>,               // amount
142  (Option<u64>, Option<u64>), // offset
143);
144
145pub(super) type RuneEntryValue = (
146  u64,                     // block
147  u128,                    // burned
148  u8,                      // divisibility
149  (u128, u128),            // etching
150  u128,                    // mints
151  u64,                     // number
152  u128,                    // premine
153  (u128, u32),             // spaced rune
154  Option<char>,            // symbol
155  Option<TermsEntryValue>, // terms
156  u64,                     // timestamp
157  bool,                    // turbo
158);
159
160impl Default for RuneEntry {
161  fn default() -> Self {
162    Self {
163      block: 0,
164      burned: 0,
165      divisibility: 0,
166      etching: Txid::all_zeros(),
167      mints: 0,
168      number: 0,
169      premine: 0,
170      spaced_rune: SpacedRune::default(),
171      symbol: None,
172      terms: None,
173      timestamp: 0,
174      turbo: false,
175    }
176  }
177}
178
179impl Entry for RuneEntry {
180  type Value = RuneEntryValue;
181
182  fn load(
183    (
184      block,
185      burned,
186      divisibility,
187      etching,
188      mints,
189      number,
190      premine,
191      (rune, spacers),
192      symbol,
193      terms,
194      timestamp,
195      turbo,
196    ): RuneEntryValue,
197  ) -> Self {
198    Self {
199      block,
200      burned,
201      divisibility,
202      etching: {
203        let low = etching.0.to_le_bytes();
204        let high = etching.1.to_le_bytes();
205        Txid::from_byte_array([
206          low[0], low[1], low[2], low[3], low[4], low[5], low[6], low[7], low[8], low[9], low[10],
207          low[11], low[12], low[13], low[14], low[15], high[0], high[1], high[2], high[3], high[4],
208          high[5], high[6], high[7], high[8], high[9], high[10], high[11], high[12], high[13],
209          high[14], high[15],
210        ])
211      },
212      mints,
213      number,
214      premine,
215      spaced_rune: SpacedRune {
216        rune: Rune(rune),
217        spacers,
218      },
219      symbol,
220      terms: terms.map(|(cap, height, amount, offset)| Terms {
221        cap,
222        height,
223        amount,
224        offset,
225      }),
226      timestamp,
227      turbo,
228    }
229  }
230
231  fn store(self) -> Self::Value {
232    (
233      self.block,
234      self.burned,
235      self.divisibility,
236      {
237        let bytes = self.etching.to_byte_array();
238        (
239          u128::from_le_bytes([
240            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
241            bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
242          ]),
243          u128::from_le_bytes([
244            bytes[16], bytes[17], bytes[18], bytes[19], bytes[20], bytes[21], bytes[22], bytes[23],
245            bytes[24], bytes[25], bytes[26], bytes[27], bytes[28], bytes[29], bytes[30], bytes[31],
246          ]),
247        )
248      },
249      self.mints,
250      self.number,
251      self.premine,
252      (self.spaced_rune.rune.0, self.spaced_rune.spacers),
253      self.symbol,
254      self.terms.map(
255        |Terms {
256           cap,
257           height,
258           amount,
259           offset,
260         }| (cap, height, amount, offset),
261      ),
262      self.timestamp,
263      self.turbo,
264    )
265  }
266}
267
268pub(super) type RuneIdValue = (u64, u32);
269
270impl Entry for RuneId {
271  type Value = RuneIdValue;
272
273  fn load((block, tx): Self::Value) -> Self {
274    Self { block, tx }
275  }
276
277  fn store(self) -> Self::Value {
278    (self.block, self.tx)
279  }
280}
281
282#[derive(Debug, Eq, PartialEq, Clone)]
283pub struct InscriptionEntry {
284  pub charms: u16,
285  pub fee: u64,
286  pub height: u32,
287  pub id: InscriptionId,
288  pub inscription_number: i32,
289  pub parents: Vec<u32>,
290  pub sat: Option<Sat>,
291  pub sequence_number: u32,
292  pub timestamp: u32,
293}
294
295pub type InscriptionEntryValue = (
296  u16,                // charms
297  u64,                // fee
298  u32,                // height
299  InscriptionIdValue, // inscription id
300  i32,                // inscription number
301  Vec<u32>,           // parents
302  Option<u64>,        // sat
303  u32,                // sequence number
304  u32,                // timestamp
305);
306
307impl Entry for InscriptionEntry {
308  type Value = InscriptionEntryValue;
309
310  #[rustfmt::skip]
311  fn load(
312    (
313      charms,
314      fee,
315      height,
316      id,
317      inscription_number,
318      parents,
319      sat,
320      sequence_number,
321      timestamp,
322    ): InscriptionEntryValue,
323  ) -> Self {
324    Self {
325      charms,
326      fee,
327      height,
328      id: InscriptionId::load(id),
329      inscription_number,
330      parents,
331      sat: sat.map(Sat),
332      sequence_number,
333      timestamp,
334    }
335  }
336
337  fn store(self) -> Self::Value {
338    (
339      self.charms,
340      self.fee,
341      self.height,
342      self.id.store(),
343      self.inscription_number,
344      self.parents,
345      self.sat.map(Sat::n),
346      self.sequence_number,
347      self.timestamp,
348    )
349  }
350}
351
352pub type InscriptionIdValue = (u128, u128, u32);
353
354impl Entry for InscriptionId {
355  type Value = InscriptionIdValue;
356
357  fn load(value: Self::Value) -> Self {
358    let (head, tail, index) = value;
359    let head_array = head.to_le_bytes();
360    let tail_array = tail.to_le_bytes();
361    let array = [
362      head_array[0],
363      head_array[1],
364      head_array[2],
365      head_array[3],
366      head_array[4],
367      head_array[5],
368      head_array[6],
369      head_array[7],
370      head_array[8],
371      head_array[9],
372      head_array[10],
373      head_array[11],
374      head_array[12],
375      head_array[13],
376      head_array[14],
377      head_array[15],
378      tail_array[0],
379      tail_array[1],
380      tail_array[2],
381      tail_array[3],
382      tail_array[4],
383      tail_array[5],
384      tail_array[6],
385      tail_array[7],
386      tail_array[8],
387      tail_array[9],
388      tail_array[10],
389      tail_array[11],
390      tail_array[12],
391      tail_array[13],
392      tail_array[14],
393      tail_array[15],
394    ];
395
396    Self {
397      txid: Txid::from_byte_array(array),
398      index,
399    }
400  }
401
402  fn store(self) -> Self::Value {
403    let txid_entry = self.txid.store();
404    let little_end = u128::from_le_bytes(txid_entry[..16].try_into().unwrap());
405    let big_end = u128::from_le_bytes(txid_entry[16..].try_into().unwrap());
406    (little_end, big_end, self.index)
407  }
408}
409
410pub type OutPointValue = [u8; 36];
411
412impl Entry for OutPoint {
413  type Value = OutPointValue;
414
415  fn load(value: Self::Value) -> Self {
416    Decodable::consensus_decode(&mut Cursor::new(value)).unwrap()
417  }
418
419  fn store(self) -> Self::Value {
420    let mut value = [0; 36];
421    self.consensus_encode(&mut value.as_mut_slice()).unwrap();
422    value
423  }
424}
425
426pub type SatPointValue = [u8; 44];
427
428impl Entry for SatPoint {
429  type Value = SatPointValue;
430
431  fn load(value: Self::Value) -> Self {
432    Decodable::consensus_decode(&mut Cursor::new(value)).unwrap()
433  }
434
435  fn store(self) -> Self::Value {
436    let mut value = [0; 44];
437    self.consensus_encode(&mut value.as_mut_slice()).unwrap();
438    value
439  }
440}
441
442pub type SatRange = (u64, u64);
443
444impl Entry for SatRange {
445  type Value = [u8; 11];
446
447  fn load([b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10]: Self::Value) -> Self {
448    let raw_base = u64::from_le_bytes([b0, b1, b2, b3, b4, b5, b6, 0]);
449
450    // 51 bit base
451    let base = raw_base & ((1 << 51) - 1);
452
453    let raw_delta = u64::from_le_bytes([b6, b7, b8, b9, b10, 0, 0, 0]);
454
455    // 33 bit delta
456    let delta = raw_delta >> 3;
457
458    (base, base + delta)
459  }
460
461  fn store(self) -> Self::Value {
462    let base = self.0;
463    let delta = self.1 - self.0;
464    let n = u128::from(base) | u128::from(delta) << 51;
465    n.to_le_bytes()[0..11].try_into().unwrap()
466  }
467}
468
469pub type TxidValue = [u8; 32];
470
471impl Entry for Txid {
472  type Value = TxidValue;
473
474  fn load(value: Self::Value) -> Self {
475    Txid::from_byte_array(value)
476  }
477
478  fn store(self) -> Self::Value {
479    Txid::to_byte_array(self)
480  }
481}
482
483#[cfg(test)]
484mod tests {
485  use super::*;
486
487  #[test]
488  fn inscription_entry() {
489    let id = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefi0"
490      .parse::<InscriptionId>()
491      .unwrap();
492
493    let entry = InscriptionEntry {
494      charms: 0,
495      fee: 1,
496      height: 2,
497      id,
498      inscription_number: 3,
499      parents: vec![4, 5, 6],
500      sat: Some(Sat(7)),
501      sequence_number: 8,
502      timestamp: 9,
503    };
504
505    let value = (0, 1, 2, id.store(), 3, vec![4, 5, 6], Some(7), 8, 9);
506
507    assert_eq!(entry.clone().store(), value);
508    assert_eq!(InscriptionEntry::load(value), entry);
509  }
510
511  #[test]
512  fn inscription_id_entry() {
513    let inscription_id = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefi0"
514      .parse::<InscriptionId>()
515      .unwrap();
516
517    assert_eq!(
518      inscription_id.store(),
519      (
520        0x0123456789abcdef0123456789abcdef,
521        0x0123456789abcdef0123456789abcdef,
522        0
523      )
524    );
525
526    assert_eq!(
527      InscriptionId::load((
528        0x0123456789abcdef0123456789abcdef,
529        0x0123456789abcdef0123456789abcdef,
530        0
531      )),
532      inscription_id
533    );
534  }
535
536  #[test]
537  fn parent_entry_index() {
538    let inscription_id = "0000000000000000000000000000000000000000000000000000000000000000i1"
539      .parse::<InscriptionId>()
540      .unwrap();
541
542    assert_eq!(inscription_id.store(), (0, 0, 1));
543
544    assert_eq!(InscriptionId::load((0, 0, 1)), inscription_id);
545
546    let inscription_id = "0000000000000000000000000000000000000000000000000000000000000000i256"
547      .parse::<InscriptionId>()
548      .unwrap();
549
550    assert_eq!(inscription_id.store(), (0, 0, 256));
551
552    assert_eq!(InscriptionId::load((0, 0, 256)), inscription_id);
553  }
554
555  #[test]
556  fn rune_entry() {
557    let entry = RuneEntry {
558      block: 12,
559      burned: 1,
560      divisibility: 3,
561      etching: Txid::from_byte_array([
562        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
563        0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
564        0x1E, 0x1F,
565      ]),
566      terms: Some(Terms {
567        cap: Some(1),
568        height: (Some(2), Some(3)),
569        amount: Some(4),
570        offset: (Some(5), Some(6)),
571      }),
572      mints: 11,
573      number: 6,
574      premine: 12,
575      spaced_rune: SpacedRune {
576        rune: Rune(7),
577        spacers: 8,
578      },
579      symbol: Some('a'),
580      timestamp: 10,
581      turbo: true,
582    };
583
584    let value = (
585      12,
586      1,
587      3,
588      (
589        0x0F0E0D0C0B0A09080706050403020100,
590        0x1F1E1D1C1B1A19181716151413121110,
591      ),
592      11,
593      6,
594      12,
595      (7, 8),
596      Some('a'),
597      Some((Some(1), (Some(2), Some(3)), Some(4), (Some(5), Some(6)))),
598      10,
599      true,
600    );
601
602    assert_eq!(entry.store(), value);
603    assert_eq!(RuneEntry::load(value), entry);
604  }
605
606  #[test]
607  fn rune_id_entry() {
608    assert_eq!(RuneId { block: 1, tx: 2 }.store(), (1, 2),);
609
610    assert_eq!(RuneId { block: 1, tx: 2 }, RuneId::load((1, 2)),);
611  }
612
613  #[test]
614  fn header() {
615    let expected = [
616      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
617      26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
618      49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
619      72, 73, 74, 75, 76, 77, 78, 79,
620    ];
621
622    let header = Header::load(expected);
623    let actual = header.store();
624
625    assert_eq!(actual, expected);
626  }
627
628  #[test]
629  fn mintable_default() {
630    assert_eq!(RuneEntry::default().mintable(0), Err(MintError::Unmintable));
631  }
632
633  #[test]
634  fn mintable_cap() {
635    assert_eq!(
636      RuneEntry {
637        terms: Some(Terms {
638          cap: Some(1),
639          amount: Some(1000),
640          ..default()
641        }),
642        mints: 0,
643        ..default()
644      }
645      .mintable(0),
646      Ok(1000),
647    );
648
649    assert_eq!(
650      RuneEntry {
651        terms: Some(Terms {
652          cap: Some(1),
653          amount: Some(1000),
654          ..default()
655        }),
656        mints: 1,
657        ..default()
658      }
659      .mintable(0),
660      Err(MintError::Cap(1)),
661    );
662
663    assert_eq!(
664      RuneEntry {
665        terms: Some(Terms {
666          cap: None,
667          amount: Some(1000),
668          ..default()
669        }),
670        mints: 0,
671        ..default()
672      }
673      .mintable(0),
674      Err(MintError::Cap(0)),
675    );
676  }
677
678  #[test]
679  fn mintable_offset_start() {
680    assert_eq!(
681      RuneEntry {
682        block: 1,
683        terms: Some(Terms {
684          cap: Some(1),
685          amount: Some(1000),
686          offset: (Some(1), None),
687          ..default()
688        }),
689        mints: 0,
690        ..default()
691      }
692      .mintable(1),
693      Err(MintError::Start(2)),
694    );
695
696    assert_eq!(
697      RuneEntry {
698        block: 1,
699        terms: Some(Terms {
700          cap: Some(1),
701          amount: Some(1000),
702          offset: (Some(1), None),
703          ..default()
704        }),
705        mints: 0,
706        ..default()
707      }
708      .mintable(2),
709      Ok(1000),
710    );
711  }
712
713  #[test]
714  fn mintable_offset_end() {
715    assert_eq!(
716      RuneEntry {
717        block: 1,
718        terms: Some(Terms {
719          cap: Some(1),
720          amount: Some(1000),
721          offset: (None, Some(1)),
722          ..default()
723        }),
724        mints: 0,
725        ..default()
726      }
727      .mintable(1),
728      Ok(1000),
729    );
730
731    assert_eq!(
732      RuneEntry {
733        block: 1,
734        terms: Some(Terms {
735          cap: Some(1),
736          amount: Some(1000),
737          offset: (None, Some(1)),
738          ..default()
739        }),
740        mints: 0,
741        ..default()
742      }
743      .mintable(2),
744      Err(MintError::End(2)),
745    );
746  }
747
748  #[test]
749  fn mintable_height_start() {
750    assert_eq!(
751      RuneEntry {
752        terms: Some(Terms {
753          cap: Some(1),
754          amount: Some(1000),
755          height: (Some(1), None),
756          ..default()
757        }),
758        mints: 0,
759        ..default()
760      }
761      .mintable(0),
762      Err(MintError::Start(1)),
763    );
764
765    assert_eq!(
766      RuneEntry {
767        terms: Some(Terms {
768          cap: Some(1),
769          amount: Some(1000),
770          height: (Some(1), None),
771          ..default()
772        }),
773        mints: 0,
774        ..default()
775      }
776      .mintable(1),
777      Ok(1000),
778    );
779  }
780
781  #[test]
782  fn mintable_height_end() {
783    assert_eq!(
784      RuneEntry {
785        terms: Some(Terms {
786          cap: Some(1),
787          amount: Some(1000),
788          height: (None, Some(1)),
789          ..default()
790        }),
791        mints: 0,
792        ..default()
793      }
794      .mintable(0),
795      Ok(1000),
796    );
797
798    assert_eq!(
799      RuneEntry {
800        terms: Some(Terms {
801          cap: Some(1),
802          amount: Some(1000),
803          height: (None, Some(1)),
804          ..default()
805        }),
806        mints: 0,
807        ..default()
808      }
809      .mintable(1),
810      Err(MintError::End(1)),
811    );
812  }
813
814  #[test]
815  fn mintable_multiple_terms() {
816    let entry = RuneEntry {
817      terms: Some(Terms {
818        cap: Some(1),
819        amount: Some(1000),
820        height: (Some(10), Some(20)),
821        offset: (Some(0), Some(10)),
822      }),
823      block: 10,
824      mints: 0,
825      ..default()
826    };
827
828    assert_eq!(entry.mintable(10), Ok(1000));
829
830    {
831      let mut entry = entry;
832      entry.terms.as_mut().unwrap().cap = None;
833      assert_eq!(entry.mintable(10), Err(MintError::Cap(0)));
834    }
835
836    {
837      let mut entry = entry;
838      entry.terms.as_mut().unwrap().height.0 = Some(11);
839      assert_eq!(entry.mintable(10), Err(MintError::Start(11)));
840    }
841
842    {
843      let mut entry = entry;
844      entry.terms.as_mut().unwrap().height.1 = Some(10);
845      assert_eq!(entry.mintable(10), Err(MintError::End(10)));
846    }
847
848    {
849      let mut entry = entry;
850      entry.terms.as_mut().unwrap().offset.0 = Some(1);
851      assert_eq!(entry.mintable(10), Err(MintError::Start(11)));
852    }
853
854    {
855      let mut entry = entry;
856      entry.terms.as_mut().unwrap().offset.1 = Some(0);
857      assert_eq!(entry.mintable(10), Err(MintError::End(10)));
858    }
859  }
860
861  #[test]
862  fn supply() {
863    assert_eq!(
864      RuneEntry {
865        terms: Some(Terms {
866          amount: Some(1000),
867          ..default()
868        }),
869        mints: 0,
870        ..default()
871      }
872      .supply(),
873      0
874    );
875
876    assert_eq!(
877      RuneEntry {
878        terms: Some(Terms {
879          amount: Some(1000),
880          ..default()
881        }),
882        mints: 1,
883        ..default()
884      }
885      .supply(),
886      1000
887    );
888
889    assert_eq!(
890      RuneEntry {
891        terms: Some(Terms {
892          amount: Some(1000),
893          ..default()
894        }),
895        mints: 0,
896        premine: 1,
897        ..default()
898      }
899      .supply(),
900      1
901    );
902
903    assert_eq!(
904      RuneEntry {
905        terms: Some(Terms {
906          amount: Some(1000),
907          ..default()
908        }),
909        mints: 1,
910        premine: 1,
911        ..default()
912      }
913      .supply(),
914      1001
915    );
916  }
917}