state explorer address validation
contract submit dialog pop fix program full trace fix address to byte array util program play on real repository fix system properties cleanup addressStringToBytes address fix documentation and unit tests
This commit is contained in:
parent
a1f44371db
commit
be6c888184
|
@ -14,6 +14,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import org.spongycastle.util.encoders.DecoderException;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
public class Utils {
|
||||
|
@ -63,6 +64,22 @@ public class Utils {
|
|||
return result.toString() + "·(" + "10^" + pow + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a hex string to address bytes and checks validity
|
||||
*
|
||||
* @param hex - a hex string of the address, e.g., 6c386a4b26f73c802f34673f7248bb118f97424a
|
||||
* @return - decode and validated address byte[]
|
||||
*/
|
||||
public static byte[] addressStringToBytes(String hex) {
|
||||
byte[] addr = null;
|
||||
try { addr = Hex.decode(hex); }
|
||||
catch(DecoderException addressIsNotValid) { return null; }
|
||||
|
||||
if(isValidAddress(addr))
|
||||
return addr;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isValidAddress(byte[] addr) {
|
||||
return addr != null && addr.length == 20;
|
||||
}
|
||||
|
|
|
@ -617,13 +617,15 @@ public class Program {
|
|||
ContractDetails contractDetails = this.result.getRepository().
|
||||
getContractDetails(this.programAddress.getLast20Bytes());
|
||||
StringBuilder storageData = new StringBuilder();
|
||||
List<DataWord> storageKeys = new ArrayList<>(contractDetails.getStorage().keySet());
|
||||
Collections.sort((List<DataWord>) storageKeys);
|
||||
for (DataWord key : storageKeys) {
|
||||
storageData.append(" ").append(key).append(" -> ").
|
||||
append(contractDetails.getStorage().get(key)).append("\n");
|
||||
if(contractDetails != null) {
|
||||
List<DataWord> storageKeys = new ArrayList<>(contractDetails.getStorage().keySet());
|
||||
Collections.sort((List<DataWord>) storageKeys);
|
||||
for (DataWord key : storageKeys) {
|
||||
storageData.append(" ").append(key).append(" -> ").
|
||||
append(contractDetails.getStorage().get(key)).append("\n");
|
||||
}
|
||||
if (storageData.length() > 0) storageData.insert(0, "\n");
|
||||
}
|
||||
if (storageData.length() > 0) storageData.insert(0, "\n");
|
||||
|
||||
StringBuilder memoryData = new StringBuilder();
|
||||
StringBuilder oneLine = new StringBuilder();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.ethereum.util;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.Arrays;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
@ -59,4 +60,31 @@ public class UtilsTest {
|
|||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddressStringToBytes() {
|
||||
// valid address
|
||||
String HexStr = "6c386a4b26f73c802f34673f7248bb118f97424a";
|
||||
byte[] expected = Hex.decode(HexStr);
|
||||
byte[] result = Utils.addressStringToBytes(HexStr);
|
||||
assertEquals(Arrays.areEqual(expected, result), true);
|
||||
|
||||
// invalid address, we removed the last char so it cannot decode
|
||||
HexStr = "6c386a4b26f73c802f34673f7248bb118f97424";
|
||||
expected = null;
|
||||
result = Utils.addressStringToBytes(HexStr);
|
||||
assertEquals(expected, result);
|
||||
|
||||
// invalid address, longer than 20 bytes
|
||||
HexStr = new String(Hex.encode("I am longer than 20 bytes, i promise".getBytes()));
|
||||
expected = null;
|
||||
result = Utils.addressStringToBytes(HexStr);
|
||||
assertEquals(expected, result);
|
||||
|
||||
// invalid address, shorter than 20 bytes
|
||||
HexStr = new String(Hex.encode("I am short".getBytes()));
|
||||
expected = null;
|
||||
result = Utils.addressStringToBytes(HexStr);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
}
|
|
@ -221,19 +221,14 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog {
|
|||
}
|
||||
|
||||
private void populateContractDetails() {
|
||||
|
||||
String contractAddr = contractAddrInput.getText();
|
||||
if (contractAddr == null || contractAddr.length() == 0) {
|
||||
alertStatusMsg("");
|
||||
byte[] addr = Utils.addressStringToBytes(contractAddrInput.getText());
|
||||
if(addr == null) {
|
||||
alertStatusMsg("Not a valid contract address");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Pattern.matches("[0-9a-fA-F]+", contractAddr) || (contractAddr.length() != 40)) {
|
||||
alertStatusMsg("Not a valid contract address");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ContractDetails contractDetails = UIEthereumManager.ethereum
|
||||
.getRepository().getContractDetails(Hex.decode(contractAddr));
|
||||
.getRepository().getContractDetails(addr);
|
||||
if (contractDetails == null) {
|
||||
alertStatusMsg("No contract for that address");
|
||||
return;
|
||||
|
@ -316,15 +311,15 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog {
|
|||
this.repaint();
|
||||
}
|
||||
|
||||
private void playContractCall() {
|
||||
|
||||
String contractAddr = contractAddrInput.getText();
|
||||
if (!Pattern.matches("[0-9a-fA-F]+", contractAddr) || (contractAddr.length() != 40)) {
|
||||
alertStatusMsg("Not a valid contract address");
|
||||
private void playContractCall() {
|
||||
byte[] addr = Utils.addressStringToBytes(contractAddrInput.getText());
|
||||
if(addr == null) {
|
||||
alertStatusMsg("Not a valid contract address");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ContractDetails contractDetails = UIEthereumManager.ethereum
|
||||
.getRepository().getContractDetails(Hex.decode(contractAddr));
|
||||
.getRepository().getContractDetails(addr);
|
||||
if (contractDetails == null) {
|
||||
alertStatusMsg("No contract for that address");
|
||||
return;
|
||||
|
|
|
@ -207,6 +207,8 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
|
|||
this.getContentPane().revalidate();
|
||||
this.getContentPane().repaint();
|
||||
this.setResizable(false);
|
||||
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
protected JRootPane createRootPane() {
|
||||
|
@ -231,7 +233,6 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
|
|||
rootPane.getActionMap().put("ESCAPE", actionListener);
|
||||
|
||||
this.setSize(500, 430);
|
||||
this.setVisible(true);
|
||||
return rootPane;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,18 +34,16 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
|||
private ProgramInvoke pi;
|
||||
|
||||
public ProgramPlayDialog(byte[] code) {
|
||||
this(code, new ProgramInvokeMockImpl(), null);
|
||||
this(code, new ProgramInvokeMockImpl());
|
||||
}
|
||||
|
||||
public ProgramPlayDialog(byte[] code, Transaction tx, Block lastBlock) {
|
||||
this(code,
|
||||
ProgramInvokeFactory.createProgramInvoke(tx,
|
||||
lastBlock,
|
||||
WorldManager.getInstance().getRepository()),
|
||||
WorldManager.getInstance().getRepository());
|
||||
this(code, ProgramInvokeFactory.createProgramInvoke(tx,
|
||||
lastBlock,
|
||||
WorldManager.getInstance().getRepository()));
|
||||
}
|
||||
|
||||
public ProgramPlayDialog(byte[] code, ProgramInvoke programInvoke, Repository tractRepository) {
|
||||
public ProgramPlayDialog(byte[] code, ProgramInvoke programInvoke) {
|
||||
pi = programInvoke;
|
||||
|
||||
outputList = new ArrayList<String>();
|
||||
|
@ -56,8 +54,8 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
|||
program.fullTrace();
|
||||
vm.play(program);
|
||||
|
||||
if(tractRepository != null)
|
||||
tractRepository.rollback();
|
||||
if(programInvoke.getRepository() != null)
|
||||
programInvoke.getRepository().rollback();
|
||||
|
||||
doGUI();
|
||||
}
|
||||
|
@ -134,7 +132,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
|||
* this method should be invoked from the
|
||||
* event-dispatching thread.
|
||||
*/
|
||||
public static void createAndShowGUI(byte[] runCode, Transaction tx, Block lastBlock) {
|
||||
public static void createAndShowGUI(byte[] runCode, final Transaction tx, Block lastBlock) {
|
||||
|
||||
final ProgramPlayDialog ppd;
|
||||
if (tx != null)
|
||||
|
@ -162,7 +160,10 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
|||
frame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
||||
ppd.pi.getRepository().close();
|
||||
if (tx == null) {
|
||||
ppd.pi.getRepository().close();
|
||||
ppd.pi = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.ethereum.core.Block;
|
|||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.util.Utils;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.ethereum.vm.OpCode;
|
||||
import org.ethereum.vm.Program;
|
||||
|
@ -50,6 +51,7 @@ import org.ethereum.vm.ProgramInvokeFactory;
|
|||
import org.ethereum.vm.Program.ProgramListener;
|
||||
import org.spongycastle.util.encoders.DecoderException;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.FlowLayout;
|
||||
|
||||
|
@ -121,7 +123,9 @@ public class StateExplorerWindow extends JFrame{
|
|||
btnSearch.addMouseListener(new MouseAdapter(){
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
searchAccount(txfAccountAddress.getText());
|
||||
byte[] addr = Utils.addressStringToBytes(txfAccountAddress.getText());
|
||||
if(addr != null)
|
||||
searchAccount(addr);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -130,9 +134,12 @@ public class StateExplorerWindow extends JFrame{
|
|||
btnPlayCode.addMouseListener(new MouseAdapter(){
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
byte[] code = WorldManager.getInstance().getRepository().getCode(Hex.decode(txfAccountAddress.getText()));
|
||||
if(code != null)
|
||||
ProgramPlayDialog.createAndShowGUI(code, null, null);
|
||||
byte[] addr = Utils.addressStringToBytes(txfAccountAddress.getText());
|
||||
if(addr != null) {
|
||||
byte[] code = WorldManager.getInstance().getRepository().getCode(addr);
|
||||
if(code != null)
|
||||
ProgramPlayDialog.createAndShowGUI(code, null, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -202,13 +209,8 @@ public class StateExplorerWindow extends JFrame{
|
|||
panel.add(scrollPane);
|
||||
}
|
||||
|
||||
private void searchAccount(String accountStr){
|
||||
private void searchAccount(byte[] add){
|
||||
txaPrinter.clean();
|
||||
|
||||
byte[] add = null;
|
||||
try { add = Hex.decode(txfAccountAddress.getText()); }
|
||||
catch(DecoderException ex) { return; }
|
||||
|
||||
txaPrinter.println(accountDetailsString(add, dataModel));
|
||||
}
|
||||
|
||||
|
@ -349,5 +351,5 @@ public class StateExplorerWindow extends JFrame{
|
|||
new StateExplorerWindow(null).setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue