ToData decodes the blob into raw byte data. See FromData above for details on the encoding format. If error is returned it will be one of InvalidFieldElementError, InvalidEncodingVersionError and InvalidLengthError.
(b []byte)
| 141 | // format. If error is returned it will be one of InvalidFieldElementError, |
| 142 | // InvalidEncodingVersionError and InvalidLengthError. |
| 143 | func ToData(b []byte) ([]byte, error) { |
| 144 | // check the version |
| 145 | if b[VersionOffset] != EncodingVersion { |
| 146 | return nil, fmt.Errorf( |
| 147 | "%w: expected version %d, got %d", ErrBlobInvalidEncodingVersion, EncodingVersion, b[VersionOffset]) |
| 148 | } |
| 149 | |
| 150 | // decode the 3-byte big-endian length value into a 4-byte integer |
| 151 | outputLen := uint32(b[2])<<16 | uint32(b[3])<<8 | uint32(b[4]) |
| 152 | if outputLen > MaxBlobDataSize { |
| 153 | return nil, fmt.Errorf("%w: got %d", ErrBlobInvalidLength, outputLen) |
| 154 | } |
| 155 | |
| 156 | // round 0 is special cased to copy only the remaining 27 bytes of the first field element into |
| 157 | // the output due to version/length encoding already occupying its first 5 bytes. |
| 158 | output := make([]byte, MaxBlobDataSize) |
| 159 | copy(output[0:27], b[5:]) |
| 160 | |
| 161 | // now process remaining 3 field elements to complete round 0 |
| 162 | opos := 28 // current position into output buffer |
| 163 | ipos := 32 // current position into the input blob |
| 164 | var err error |
| 165 | encodedByte := make([]byte, 4) // buffer for the 4 6-bit chunks |
| 166 | encodedByte[0] = b[0] |
| 167 | for i := 1; i < 4; i++ { |
| 168 | encodedByte[i], opos, ipos, err = decodeFieldElement(b, opos, ipos, output) |
| 169 | if err != nil { |
| 170 | return nil, err |
| 171 | } |
| 172 | } |
| 173 | opos = reassembleBytes(opos, encodedByte, output) |
| 174 | |
| 175 | // in each remaining round we decode 4 field elements (128 bytes) of the input into 127 bytes |
| 176 | // of output |
| 177 | for i := 1; i < Rounds && opos < int(outputLen); i++ { |
| 178 | for j := 0; j < 4; j++ { |
| 179 | // save the first byte of each field element for later re-assembly |
| 180 | encodedByte[j], opos, ipos, err = decodeFieldElement(b, opos, ipos, output) |
| 181 | if err != nil { |
| 182 | return nil, err |
| 183 | } |
| 184 | } |
| 185 | opos = reassembleBytes(opos, encodedByte, output) |
| 186 | } |
| 187 | for i := int(outputLen); i < len(output); i++ { |
| 188 | if output[i] != 0 { |
| 189 | return nil, fmt.Errorf("fe=%d: %w", opos/32, ErrBlobExtraneousDataFieldElement) |
| 190 | } |
| 191 | } |
| 192 | output = output[:outputLen] |
| 193 | for ; ipos < BlobSize; ipos++ { |
| 194 | if b[ipos] != 0 { |
| 195 | return nil, fmt.Errorf("pos=%d: %w", ipos, ErrBlobExtraneousData) |
| 196 | } |
| 197 | } |
| 198 | return output, nil |
| 199 | } |
| 200 |