github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/astrobwt/astrobwt.go (about) 1 package astrobwt 2 3 //import "fmt" 4 import "strings" 5 import "errors" 6 import "sort" 7 import "golang.org/x/crypto/sha3" 8 import "encoding/binary" 9 import "golang.org/x/crypto/salsa20/salsa" 10 11 // see here to improve the algorithms more https://github.com/y-256/libdivsufsort/blob/wiki/SACA_Benchmarks.md 12 13 // ErrInvalidSuffixArray means length of sa is not equal to 1+len(s) 14 var ErrInvalidSuffixArray = errors.New("bwt: invalid suffix array") 15 16 // Transform returns Burrows–Wheeler transform of a byte slice. 17 // See https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform 18 func Transform(s []byte, es byte) ([]byte, error) { 19 sa := SuffixArray(s) 20 bwt, err := FromSuffixArray(s, sa, es) 21 return bwt, err 22 } 23 24 // InverseTransform reverses the bwt to original byte slice. Not optimized yet. 25 func InverseTransform(t []byte, es byte) []byte { 26 27 le := len(t) 28 table := make([]string, le) 29 for range table { 30 for i := 0; i < le; i++ { 31 table[i] = string(t[i:i+1]) + table[i] 32 } 33 sort.Strings(table) 34 } 35 for _, row := range table { 36 if strings.HasSuffix(row, "$") { 37 return []byte(row[:le-1]) 38 } 39 } 40 return []byte("") 41 42 /* 43 n := len(t) 44 lines := make([][]byte, n) 45 for i := 0; i < n; i++ { 46 lines[i] = make([]byte, n) 47 } 48 49 for i := 0; i < n; i++ { 50 for j := 0; j < n; j++ { 51 lines[j][n-1-i] = t[j] 52 } 53 sort.Sort(byteutil.SliceOfByteSlice(lines)) 54 } 55 56 s := make([]byte, n-1) 57 for _, line := range lines { 58 if line[n-1] == es { 59 s = line[0 : n-1] 60 break 61 } 62 } 63 return s 64 */ 65 } 66 67 // SuffixArray returns the suffix array of s. 68 func SuffixArray(s []byte) []int { 69 _sa := New(s) 70 var sa []int = make([]int, len(s)+1) 71 sa[0] = len(s) 72 for i := 0; i < len(s); i++ { 73 sa[i+1] = int(_sa.sa.int32[i]) 74 } 75 return sa 76 } 77 78 // FromSuffixArray compute BWT from sa 79 func FromSuffixArray(s []byte, sa []int, es byte) ([]byte, error) { 80 if len(s)+1 != len(sa) || sa[0] != len(s) { 81 return nil, ErrInvalidSuffixArray 82 } 83 bwt := make([]byte, len(sa)) 84 bwt[0] = s[len(s)-1] 85 for i := 1; i < len(sa); i++ { 86 if sa[i] == 0 { 87 bwt[i] = es 88 } else { 89 bwt[i] = s[sa[i]-1] 90 } 91 } 92 return bwt, nil 93 } 94 95 func BWT(input []byte) ([]byte, int) { 96 if len(input) >= maxData32 { 97 panic("input too big to handle") 98 } 99 sa := make([]int32, len(input)+1) 100 text_32(input, sa[1:]) 101 102 bwt := make([]byte, len(input)+1) 103 bwt[0] = input[len(input)-1] 104 emarker := 0 105 for i := 1; i < len(sa); i++ { 106 if sa[i] == 0 { 107 //bwt[i] = '$' //es 108 emarker = i 109 } else { 110 bwt[i] = input[sa[i]-1] 111 } 112 113 } 114 //bwt[emarker] = '$' 115 return bwt, emarker 116 } 117 118 const stage1_length int = 147253 // it is a prime 119 const MAX_LENGTH int = 1024*1024 + stage1_length + 1024 120 121 func POW(inputdata []byte) (outputhash [32]byte) { 122 123 var counter [16]byte 124 125 key := sha3.Sum256(inputdata) 126 127 var stage1 [stage1_length]byte // stages are taken from it 128 var stage2 [1024*1024 + stage1_length + 1024]byte 129 130 salsa.XORKeyStream(stage1[:stage1_length], stage1[:stage1_length], &counter, &key) 131 132 stage1_result, eos := BWT(stage1[:stage1_length]) 133 134 key = sha3.Sum256(stage1_result) 135 136 stage2_length := stage1_length + int(binary.LittleEndian.Uint32(key[:])&0xfffff) 137 138 for i := range counter { // will be optimized by compiler 139 counter[i] = 0 140 } 141 142 salsa.XORKeyStream(stage2[:stage2_length], stage2[:stage2_length], &counter, &key) 143 144 stage2_result, eos := BWT(stage2[:stage2_length]) 145 146 // fmt.Printf("result %x stage2_length %d \n", key, stage2_length) 147 key = sha3.Sum256(stage2_result) 148 149 //fmt.Printf("result %x\n", key) 150 151 copy(outputhash[:], key[:]) 152 153 _ = eos 154 return 155 } 156 157 // input byte 158 // sa should be len(input) + 1 159 // result len len(input) + 1 160 func BWT_0alloc(input []byte, sa []int32, bwt []byte) int { 161 162 //ix := &Index{data: input} 163 if len(input) >= maxData32 { 164 panic("input too big to handle") 165 } 166 if len(sa) != len(input)+1 { 167 panic("invalid sa array") 168 } 169 if len(bwt) != len(input)+1 { 170 panic("invalid bwt array") 171 } 172 //sa := make([]int32, len(input)+1) 173 text_32(input, sa[1:]) 174 175 //bwt := make([]byte, len(input)+1) 176 bwt[0] = input[len(input)-1] 177 emarker := 0 178 for i := 1; i < len(sa); i++ { 179 if sa[i] == 0 { 180 //bwt[i] = '$' //es 181 emarker = i 182 } else { 183 bwt[i] = input[sa[i]-1] 184 } 185 186 } 187 //bwt[emarker] = '$' 188 return emarker 189 } 190 func POW_0alloc(inputdata []byte) (outputhash [32]byte) { 191 192 var counter [16]byte 193 194 var sa [MAX_LENGTH]int32 195 // var bwt [max_length]int32 196 197 var stage1 [stage1_length]byte // stages are taken from it 198 var stage1_result [stage1_length + 1]byte 199 var stage2 [1024*1024 + stage1_length + 1]byte 200 var stage2_result [1024*1024 + stage1_length + 1]byte 201 202 key := sha3.Sum256(inputdata) 203 204 salsa.XORKeyStream(stage1[:stage1_length], stage1[:stage1_length], &counter, &key) 205 206 eos := BWT_0alloc(stage1[:stage1_length], sa[:stage1_length+1], stage1_result[:stage1_length+1]) 207 208 key = sha3.Sum256(stage1_result[:]) 209 210 stage2_length := stage1_length + int(binary.LittleEndian.Uint32(key[:])&0xfffff) 211 212 for i := range counter { // will be optimized by compiler 213 counter[i] = 0 214 } 215 216 salsa.XORKeyStream(stage2[:stage2_length], stage2[:stage2_length], &counter, &key) 217 218 for i := range sa { 219 sa[i] = 0 220 } 221 222 eos = BWT_0alloc(stage2[:stage2_length], sa[:stage2_length+1], stage2_result[:stage2_length+1]) 223 _ = eos 224 225 key = sha3.Sum256(stage2_result[:stage2_length+1]) 226 227 copy(outputhash[:], key[:]) 228 return 229 }