Я пытаюсь интегрировать 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 и может загрузить тот же файл кошелька. Может ли кто-нибудь сказать мне, как это решить?
Нашел быстрый лайфхак. Создайте 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 ЭТО ОСНОВНАЯ ПРОБЛЕМА
мтфк
useFullScrypt
что было установленоtrue
, чтобыfalse
решить проблему. У меня еще не было времени исследовать проблему, но, как я проверил, параметры KPF в этих случаях разные.