Excepción de falta de memoria cuando se usa web3j en Android

Estoy tratando de integrar web3j en una aplicación de Android. Pero la biblioteca da una excepción de memoria insuficiente al cargar el archivo de la billetera:

Credentials credentials = WalletUtils.loadCredentials("password", walletFile)

Esta es la excepción:

java.lang.OutOfMemoryError: Failed to allocate a 268435468 byte allocation with 8050708 free bytes and 244MB until OOM

Este parece ser el culpable:

//com.lambdaworks.crypto.SCrypt#scryptJ
byte[] V  = new byte[128 * r * N]; // r: 8, N: 262144, V = byte[268435456]

Sé que las credenciales se pueden cargar porque otro proyecto, Ether Wallet , usa web3j y puede cargar el mismo archivo de billetera. ¿Alguien puede decirme cómo solucionar esto?

Obtuve exactamente el mismo error al intentar crear una billetera. En mi caso, el problema era useFullScryptcuál estaba configurado para trueconfigurarlo para falseresolver el problema. Todavía no tuve tiempo de investigar el problema, pero como verifiqué, los parámetros KPF son diferentes en esos casos.

Respuestas (2)

Encontré un truco rápido. Cree una jniLibscarpeta /src/mainy agregue todas las carpetas de Android de esta bifurcación de scrypt a la jniLibscarpeta. Construir. Correr

Actualizaré con una solución más correcta si/cuando encuentre una.

Nota: Requiere gradle 0.7.2+ para que jniLibs se agregue a la compilación automáticamente

Esto todavía está sucediendo.

método de descifrado ( org.web3j.crypto) llamadas generadasDerivedScryptKey ( org.web3j.crypto) llamadas generadas en SCrypt ( org.spongycastle.crypto.generators)..

todo se reduce al tamaño del Array, inicializado por el parámetro N:

WalletFile.KdfParams kdfParams = crypto.getKdfparams();
if (kdfParams instanceof WalletFile.ScryptKdfParams) {
    WalletFile.ScryptKdfParams scryptKdfParams =
                (WalletFile.ScryptKdfParams) crypto.getKdfparams();
    int dklen = scryptKdfParams.getDklen();
    int n = scryptKdfParams.getN();
    int p = scryptKdfParams.getP();
    int r = scryptKdfParams.getR();
    byte[] salt = Numeric.hexStringToByteArray(scryptKdfParams.getSalt());
    derivedKey = generateDerivedScryptKey(
                password.getBytes(Charset.forName("UTF-8")), salt, n, r, p, dklen);

N ES EL PROBLEMA CENTRAL