/*
* Copyright (c) [2016] [ <ether.camp> ]
* This file is part of the ethereumJ library.
*
* The ethereumJ library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ethereumJ library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ethereum.jsontestsuite.suite.validators;
import org.ethereum.core.AccountState;
import org.ethereum.db.ContractDetails;
import org.ethereum.vm.DataWord;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.*;
public class AccountValidator {
public static List<String> valid(String address, AccountState expectedState, ContractDetails expectedDetails,
AccountState currentState, ContractDetails currentDetails){
List<String> results = new ArrayList<>();
if (currentState == null || currentDetails == null){
String formattedString = String.format("Account: %s: expected but doesn't exist",
address);
results.add(formattedString);
return results;
}
if (expectedState == null || expectedDetails == null){
String formattedString = String.format("Account: %s: unexpected account in the repository",
address);
results.add(formattedString);
return results;
}
BigInteger expectedBalance = expectedState.getBalance();
if (currentState.getBalance().compareTo(expectedBalance) != 0) {
String formattedString = String.format("Account: %s: has unexpected balance, expected balance: %s found balance: %s",
address, expectedBalance.toString(), currentState.getBalance().toString());
results.add(formattedString);
}
BigInteger expectedNonce = expectedState.getNonce();
if (currentState.getNonce().compareTo(expectedNonce) != 0) {
String formattedString = String.format("Account: %s: has unexpected nonce, expected nonce: %s found nonce: %s",
address, expectedNonce.toString(), currentState.getNonce().toString());
results.add(formattedString);
}
byte[] code = currentDetails.getCode();
if (!Arrays.equals(expectedDetails.getCode(), code)) {
String formattedString = String.format("Account: %s: has unexpected code, expected code: %s found code: %s",
address, Hex.toHexString(expectedDetails.getCode()), Hex.toHexString(currentDetails.getCode()));
results.add(formattedString);
}
// compare storage
Set<DataWord> expectedKeys = expectedDetails.getStorage().keySet();
for (DataWord key : expectedKeys) {
// force to load known keys to cache to enumerate them
currentDetails.get(key);
}
Set<DataWord> currentKeys = currentDetails.getStorage().keySet();
Set<DataWord> checked = new HashSet<>();
for (DataWord key : currentKeys) {
DataWord currentValue = currentDetails.getStorage().get(key);
DataWord expectedValue = expectedDetails.getStorage().get(key);
if (expectedValue == null) {
String formattedString = String.format("Account: %s: has unexpected storage data: %s = %s",
address,
key,
currentValue);
results.add(formattedString);
continue;
}
if (!expectedValue.equals(currentValue)) {
String formattedString = String.format("Account: %s: has unexpected value, for key: %s , expectedValue: %s real value: %s",
address,
key.toString(),
expectedValue.toString(), currentValue.toString());
results.add(formattedString);
continue;
}
checked.add(key);
}
for (DataWord key : expectedKeys) {
if (!checked.contains(key)) {
String formattedString = String.format("Account: %s: doesn't exist expected storage key: %s",
address, key.toString());
results.add(formattedString);
}
}
return results;
}
}