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:
Alon Muroch 2014-09-20 12:31:31 +03:00
parent a1f44371db
commit be6c888184
7 changed files with 93 additions and 47 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}
});

View File

@ -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);
}
});
}
}
}