## Nim-Libp2p ## Copyright (c) 2018 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## at your option. ## This file may not be copied, modified, or distributed except according to ## those terms. ## This module implements BASE58 encoding and decoding procedures. ## This module supports two variants of BASE58 encoding (Bitcoin and Flickr). import errors export errors type Base58Alphabet* = object decode*: array[128, int8] encode*: array[58, uint8] BTCBase58* = object ## Type to use Bitcoin alphabet FLCBase58* = object ## Type to use Flickr alphabet Base58* = BtcBase58 ## By default we are using Bitcoin alphabet Base58C* = BTCBase58 | FLCBase58 ## Supported types Base58Error* = object of CatchableError ## Base58 specific exception type proc newAlphabet58*(s: string): Base58Alphabet = doAssert(len(s) == 58) for i in 0..= encodedLength(len(inbytes))``. when btype is BTCBase58: const alphabet = BTCAlphabet elif btype is FLCBase58: const alphabet = FlickrAlphabet let binsz = len(inbytes) var zcount = 0 while zcount < binsz and inbytes[zcount] == 0x00'u8: inc(zcount) let size = ((binsz - zcount) * 138) div 100 + 1 var buffer = newSeq[uint8](size) var hi = size - 1 var i = zcount var j = size - 1 while i < binsz: var carry = uint32(inbytes[i]) j = size - 1 while (j > hi) or (carry != 0'u32): carry = carry + uint32(256'u32 * buffer[j]) buffer[j] = cast[byte](carry mod 58) carry = carry div 58 dec(j) hi = j inc(i) j = 0 while (j < size) and (buffer[j] == 0x00'u8): inc(j) let needed = zcount + size - j if len(outstr) < needed: result.err(errors.OverrunError) else: for k in 0..= decodedLength(len(instr))``. when btype is BTCBase58: const alphabet = BTCAlphabet elif btype is FLCBase58: const alphabet = FlickrAlphabet var outlen = 0 if len(instr) == 0: result.ok(0) return let binsz = len(instr) + 4 if len(outbytes) < binsz: result.err(errors.OverrunError) return var bytesleft = binsz mod 4 var zeromask: uint32 if bytesleft != 0: zeromask = cast[uint32](0xFFFF_FFFF'u32 shl (bytesleft * 8)) let size = (binsz + 3) div 4 var buffer = newSeq[uint32](size) var zcount = 0 while zcount < len(instr) and instr[zcount] == cast[char](alphabet.encode[0]): inc(zcount) for i in zcount.. m: result.err(errors.OverrunError) return break inc(m) dec(outlen) if m < binsz: moveMem(addr outbytes[zcount], addr outbytes[binsz - outlen], outlen) outlen += zcount result.ok(outlen) proc decode*(btype: typedesc[Base58C], instr: string): Result[seq[byte], errors.Error] = ## Decode BASE58 string ``instr`` and return sequence of bytes as result. var size = len(instr) + 4 var resbytes = newSeq[byte](size) let res = btype.decode(instr, resbytes) if res.isOk: resbytes.setLen(res.value) result.ok(resbytes) else: result.err(res.error)