/*
* 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.json;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.db.ContractDetails;
import org.ethereum.core.Repository;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.DataWord;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* JSON Helper class to format data into ObjectNodes
* to match PyEthereum blockstate output
*
* Dump format:
* {
* "address":
* {
* "nonce": "n1",
* "balance": "b1",
* "stateRoot": "s1",
* "codeHash": "c1",
* "code": "c2",
* "storage":
* {
* "key1": "value1",
* "key2": "value2"
* }
* }
* }
*
* @author Roman Mandeleil
* @since 26.06.2014
*/
public class JSONHelper {
@SuppressWarnings("uncheked")
public static void dumpState(ObjectNode statesNode, String address, AccountState state, ContractDetails details) {
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
Collections.sort(storageKeys);
ObjectNode account = statesNode.objectNode();
ObjectNode storage = statesNode.objectNode();
for (DataWord key : storageKeys) {
storage.put("0x" + Hex.toHexString(key.getData()),
"0x" + Hex.toHexString(details.getStorage().get(key).getNoLeadZeroesData()));
}
if (state == null)
state = new AccountState(SystemProperties.getDefault().getBlockchainConfig().getCommonConstants().getInitialNonce(),
BigInteger.ZERO);
account.put("balance", state.getBalance() == null ? "0" : state.getBalance().toString());
// account.put("codeHash", details.getCodeHash() == null ? "0x" : "0x" + Hex.toHexString(details.getCodeHash()));
account.put("code", details.getCode() == null ? "0x" : "0x" + Hex.toHexString(details.getCode()));
account.put("nonce", state.getNonce() == null ? "0" : state.getNonce().toString());
account.set("storage", storage);
account.put("storage_root", state.getStateRoot() == null ? "" : Hex.toHexString(state.getStateRoot()));
statesNode.set(address, account);
}
public static void dumpBlock(ObjectNode blockNode, Block block,
long gasUsed, byte[] state, List<ByteArrayWrapper> keys,
Repository repository) {
blockNode.put("coinbase", Hex.toHexString(block.getCoinbase()));
blockNode.put("difficulty", new BigInteger(1, block.getDifficulty()).toString());
blockNode.put("extra_data", "0x");
blockNode.put("gas_used", String.valueOf(gasUsed));
blockNode.put("nonce", "0x" + Hex.toHexString(block.getNonce()));
blockNode.put("number", String.valueOf(block.getNumber()));
blockNode.put("prevhash", "0x" + Hex.toHexString(block.getParentHash()));
ObjectNode statesNode = blockNode.objectNode();
for (ByteArrayWrapper key : keys) {
byte[] keyBytes = key.getData();
AccountState accountState = repository.getAccountState(keyBytes);
ContractDetails details = repository.getContractDetails(keyBytes);
dumpState(statesNode, Hex.toHexString(keyBytes), accountState, details);
}
blockNode.set("state", statesNode);
blockNode.put("state_root", Hex.toHexString(state));
blockNode.put("timestamp", String.valueOf(block.getTimestamp()));
ArrayNode transactionsNode = blockNode.arrayNode();
blockNode.set("transactions", transactionsNode);
blockNode.put("tx_list_root", ByteUtil.toHexString(block.getTxTrieRoot()));
blockNode.put("uncles_hash", "0x" + Hex.toHexString(block.getUnclesHash()));
// JSONHelper.dumpTransactions(blockNode,
// stateRoot, codeHash, code, storage);
}
}