Исключение «Недостаточно памяти» при использовании web3j в Android

Я пытаюсь интегрировать web3j в приложение для Android. Но библиотека выдает исключение Out Of Memory при загрузке файла кошелька:

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

Это исключение:

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

Это, кажется, виновник:

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

Я знаю, что учетные данные могут быть загружены, потому что другой проект, Ether Wallet , использует web3j и может загрузить тот же файл кошелька. Может ли кто-нибудь сказать мне, как это решить?

Я получил точно такую ​​же ошибку, когда пытался создать кошелек. В моем случае проблема заключалась в том, useFullScryptчто было установлено true, чтобы falseрешить проблему. У меня еще не было времени исследовать проблему, но, как я проверил, параметры KPF в этих случаях разные.

Ответы (2)

Нашел быстрый лайфхак. Создайте jniLibsпапку /src/mainи добавьте в нее все папки Android из этой вилки scrypt jniLibs. Строить. Бег

Я добавлю более правильное решение, если/когда найду его.

Примечание. Для автоматического добавления jniLibs в сборку требуется gradle 0.7.2+.

Это все еще происходит.

метод расшифровки ( org.web3j.crypto) вызывает вызовы generateDerivedScryptKey ( org.web3j.crypto) генерирует в SCrypt ( org.spongycastle.crypto.generators..

все сводится к размеру массива, инициализируемого параметром 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 ЭТО ОСНОВНАЯ ПРОБЛЕМА