Smart Contract
MnemonicPoetry
A.1717d6b5ee65530a.MnemonicPoetry
1import BIP39WordListJa from 0x1717d6b5ee65530a
2
3access(all) contract MnemonicPoetry {
4
5 access(all) event NewMnemonic(mnemonic: Mnemonic)
6 access(all) event NewMnemonicPoem(mnemonicPoem: MnemonicPoem)
7
8 access(all) struct Mnemonic {
9 access(all) let words: [String]
10 access(all) let blockID: [UInt8; 32]
11 access(all) let blockHeight: UInt64
12 access(all) let blockTimestamp: UFix64
13
14 init(
15 words: [String],
16 blockID: [UInt8; 32],
17 blockHeight: UInt64,
18 blockTimestamp: UFix64
19 ) {
20 self.words = words
21 self.blockID = blockID
22 self.blockHeight = blockHeight
23 self.blockTimestamp = blockTimestamp
24 }
25 }
26
27 access(all) struct MnemonicPoem {
28 access(all) let mnemonic: Mnemonic
29 access(all) let poem: String
30
31 init(
32 mnemonic: Mnemonic,
33 poem: String
34 ) {
35 self.mnemonic = mnemonic
36 self.poem = poem
37 }
38 }
39
40 access(all) resource interface PoetryCollectionPublic {
41 access(all) var mnemonics: [Mnemonic]
42 access(all) var poems: [MnemonicPoem]
43 access(all) fun getMnemonic(index: Int): Mnemonic
44 access(all) fun getPoem(index: Int): MnemonicPoem
45 }
46
47 access(all) resource PoetryCollection: PoetryCollectionPublic {
48 access(all) var mnemonics: [Mnemonic]
49 access(all) var poems: [MnemonicPoem]
50
51 init() {
52 self.mnemonics = []
53 self.poems = []
54 }
55
56 access(all) fun getMnemonic(index: Int): Mnemonic {
57 return self.mnemonics[index]
58 }
59
60 access(all) fun getPoem(index: Int): MnemonicPoem {
61 return self.poems[index]
62 }
63
64 access(all) fun findMnemonic(): Mnemonic {
65 let block = getCurrentBlock()
66 let entropyWithChecksum = self.blockIDToEntropyWithChecksum(blockID: block.id)
67 let words = self.entropyWithChecksumToWords(entropyWithChecksum: entropyWithChecksum)
68 let mnemonic = Mnemonic(
69 words: words,
70 blockID: block.id,
71 blockHeight: block.height,
72 blockTimestamp: block.timestamp
73 )
74 self.mnemonics.append(mnemonic)
75 emit NewMnemonic(mnemonic: mnemonic)
76 return mnemonic
77 }
78
79 access(self) fun blockIDToEntropyWithChecksum(blockID: [UInt8; 32]): [UInt8] {
80 var entropy: [UInt8] = []
81 var i = 0
82 while i < 16 {
83 entropy.append(blockID[i] ^ blockID[i + 16])
84 i = i + 1
85 }
86 let checksum = HashAlgorithm.SHA2_256.hash(entropy)[0]
87 var entropyWithChecksum = entropy
88 entropyWithChecksum.append(checksum)
89 return entropyWithChecksum
90 }
91
92 access(self) fun entropyWithChecksumToWords(entropyWithChecksum: [UInt8]): [String] {
93 var words: [String] = []
94 var i = 0
95 while i < 12 {
96 let index = self.extract11Bits(from: entropyWithChecksum, at: i * 11)
97 words.append(BIP39WordListJa.ja[index])
98 i = i + 1
99 }
100 return words
101 }
102
103 access(self) fun extract11Bits(from bytes: [UInt8], at bitPosition: Int): Int {
104 let bytePosition = bitPosition / 8
105 let bitOffset = bitPosition % 8
106
107 var res: UInt32 = 0
108 if bytePosition < bytes.length {
109 res = UInt32(bytes[bytePosition]) << 16
110 }
111 if bytePosition + 1 < bytes.length {
112 res = res | (UInt32(bytes[bytePosition + 1]) << 8)
113 }
114 if bitOffset > 5 && bytePosition + 2 < bytes.length {
115 res = res | UInt32(bytes[bytePosition + 2])
116 }
117
118 res = res >> UInt32(24 - 11 - bitOffset)
119 res = res & 0x7FF
120 return Int(res)
121 }
122
123 access(all) fun writePoem(mnemonic: Mnemonic, poem: String) {
124 let mnemonicPoem = MnemonicPoem(
125 mnemonic: mnemonic,
126 poem: poem
127 )
128 self.poems.append(mnemonicPoem)
129 emit NewMnemonicPoem(mnemonicPoem: mnemonicPoem)
130 }
131 }
132
133 access(all) fun createEmptyPoetryCollection(): @PoetryCollection {
134 return <- create PoetryCollection()
135 }
136}
137