diff --git a/app/src/main/java/com/samourai/wallet/segwit/bech32/Bech32Segwit.java b/app/src/main/java/com/samourai/wallet/segwit/bech32/Bech32Segwit.java index dda9e8bd4..decf0f14f 100644 --- a/app/src/main/java/com/samourai/wallet/segwit/bech32/Bech32Segwit.java +++ b/app/src/main/java/com/samourai/wallet/segwit/bech32/Bech32Segwit.java @@ -2,10 +2,6 @@ import org.apache.commons.lang3.tuple.Pair; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - public class Bech32Segwit { public static Pair decode(String hrp, String addr) throws Exception { @@ -24,11 +20,8 @@ public static Pair decode(String hrp, String addr) throws Exceptio } byte[] data = p.getRight(); - List progBytes = new ArrayList(); - for(int i = 1; i < data.length; i++) { - progBytes.add(data[i]); - } - byte[] decoded = convertBits(progBytes, 5, 8, false); + byte[] decoded = new byte[getOutSize(data.length - 1, 5, 8, false)]; + convertBits(data, 1, decoded, 0, 5, 8, false); if(decoded.length < 2 || decoded.length > 40) { throw new Exception("invalid decoded data length"); } @@ -47,32 +40,32 @@ public static Pair decode(String hrp, String addr) throws Exceptio public static String encode(String hrp, byte witnessVersion, byte[] witnessProgram) throws Exception { - List progBytes = new ArrayList(); - for(int i = 0; i < witnessProgram.length; i++) { - progBytes.add(witnessProgram[i]); - } - - byte[] prog = convertBits(progBytes, 8, 5, true); - byte[] data = new byte[1 + prog.length]; - - System.arraycopy(new byte[] { witnessVersion }, 0, data, 0, 1); - System.arraycopy(prog, 0, data, 1, prog.length); + byte[] data = new byte[1 + getOutSize(witnessProgram.length, 8, 5, true)]; + data[0] = witnessVersion; + convertBits(witnessProgram, 0, data, 1, 8, 5, true); String ret = Bech32.bech32Encode(hrp, data); return ret; } - private static byte[] convertBits(List data, int fromBits, int toBits, boolean pad) throws Exception { + private static int getOutSize(int dataSize, int fromBits, int toBits, boolean pad) { + int outSize = dataSize * fromBits / toBits; + if (pad && outSize * toBits < dataSize * fromBits) { + outSize++; + } + return outSize; + } + + private static void convertBits(byte[] src, int srcIdx, byte[] dest, int destIdx, + int fromBits, int toBits, boolean pad) throws Exception { int acc = 0; int bits = 0; int maxv = (1 << toBits) - 1; - List ret = new ArrayList(); - - for(Byte value : data) { - short b = (short)(value.byteValue() & 0xff); + for(; srcIdx < src.length; srcIdx++) { + short b = (short)(src[srcIdx] & 0xff); if (b < 0) { throw new Exception(); @@ -88,26 +81,19 @@ else if ((b >> fromBits) > 0) { bits += fromBits; while (bits >= toBits) { bits -= toBits; - ret.add((byte)((acc >> bits) & maxv)); + dest[destIdx++] = (byte)((acc >> bits) & maxv); } } if(pad && (bits > 0)) { - ret.add((byte)((acc << (toBits - bits)) & maxv)); + dest[destIdx++] = (byte)((acc << (toBits - bits)) & maxv); } else if (bits >= fromBits || (byte)(((acc << (toBits - bits)) & maxv)) != 0) { - return null; + throw new Exception(); } else { ; } - - byte[] buf = new byte[ret.size()]; - for(int i = 0; i < ret.size(); i++) { - buf[i] = ret.get(i); - } - - return buf; } public static byte[] getScriptPubkey(byte witver, byte[] witprog) {