Contract Call Dialog:

+ Play button to call already saved contracts
This commit is contained in:
romanman 2014-06-09 14:45:41 +01:00
parent a9b890a86d
commit 9ae78521a6
4 changed files with 93 additions and 22 deletions

View File

@ -1,8 +1,10 @@
package org.ethereum.gui;
import org.ethereum.core.Account;
import org.ethereum.core.AccountState;
import org.ethereum.core.Transaction;
import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.client.ClientPeer;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.Utils;
@ -32,7 +34,7 @@ import java.util.Collection;
*/
class ContractCallDialog extends JDialog implements MessageAwareDialog{
Logger logger = LoggerFactory.getLogger(getClass());
Logger logger = LoggerFactory.getLogger("ui");
ContractCallDialog dialog;
@ -79,6 +81,24 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
rejectLabel.setToolTipText("Cancel");
rejectLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
URL playIconURL = ClassLoader.getSystemResource("buttons/play.png");
ImageIcon playIcon = new ImageIcon(playIconURL);
JLabel playLabel = new JLabel(playIcon);
playLabel.setToolTipText("Play Drafted");
playLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
playLabel.addMouseListener(
new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
ContractCallDialog.this.playContractCall();
}}
);
playLabel.setBounds(438, 100, 42, 42);
this.getContentPane().add(playLabel);
JLabel statusMessage = new JLabel("");
statusMessage.setBounds(50, 360, 400, 50);
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
@ -178,6 +198,29 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
this.setResizable(false);
}
private void playContractCall() {
byte[] contractAddress = Hex.decode( contractAddrInput.getText());
byte[] contractStateB = WorldManager.instance.worldState.get(contractAddress);
if (contractStateB == null || contractStateB.length == 0){
alertStatusMsg("No contract for that address");
return;
}
AccountState contractState = new AccountState(contractStateB);
byte[] programCode = WorldManager.instance.chainDB.get(contractState.getCodeHash());
if (programCode == null || programCode.length == 0){
alertStatusMsg("Such account exist but no code in the db");
return;
}
Transaction tx = createTransaction();
if (tx == null) return;
ProgramPlayDialog.createAndShowGUI(programCode, tx, MainData.instance.getBlockchain().getLastBlock());
}
protected JRootPane createRootPane() {
Container parent = this.getParent();
@ -223,9 +266,28 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
return;
}
// todo: check up how the HEX value is encoded
Transaction tx = createTransaction();
if (tx == null) return;
if (logger.isInfoEnabled()) {
logger.info("tx.hash: {}", (new BigInteger(tx.getHash()).toString(16)));
}
// SwingWorker
DialogWorker worker = new DialogWorker(tx, this);
worker.execute();
}
private Transaction createTransaction(){
byte[] data;
if (!msgDataTA.getText().trim().equals("")){
Object[] lexaList = msgDataTA.getText().split(",");
byte[] data = ByteUtil.encodeDataList(lexaList);
data = ByteUtil.encodeDataList(lexaList);
} else {
data = new byte[]{};
}
byte[] contractAddress = Hex.decode( contractAddrInput.getText());
@ -252,23 +314,18 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
Transaction tx = new Transaction(nonce, gasPrice, gasValue,
contractAddress, endowment, data);
if (logger.isInfoEnabled()) {
logger.info("tx.hash: {}", (new BigInteger(tx.getHash()).toString(16)));
}
try {
tx.sign(senderPrivKey);
} catch (Exception e1) {
dialog.alertStatusMsg("Failed to sign the transaction");
return;
return null;
}
// SwingWorker
DialogWorker worker = new DialogWorker(tx, this);
worker.execute();
return tx;
}
public class AccountWrapper {
private Account account;

View File

@ -4,6 +4,7 @@ import org.ethereum.core.Account;
import org.ethereum.core.AccountState;
import org.ethereum.core.Transaction;
import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.client.ClientPeer;
import org.ethereum.util.Utils;
import org.spongycastle.util.BigIntegers;
@ -107,7 +108,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
}
contractAddrInput.setText(Hex.toHexString(tx.getContractAddress()));
ProgramPlayDialog.createAndShowGUI(tx);
ProgramPlayDialog.createAndShowGUI(tx.getData(), tx, MainData.instance.getBlockchain().getLastBlock());
}}
);
@ -312,7 +313,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount();
BigInteger currentBalance = account.getState().getBalance();
BigInteger gasPrice = BigInteger.valueOf( MainData.instance.getBlockchain().getGasPrice());
BigInteger gasPrice = BigInteger.valueOf(MainData.instance.getBlockchain().getGasPrice());
BigInteger gasInput = new BigInteger( this.gasInput.getText());
boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0;

View File

@ -1,5 +1,6 @@
package org.ethereum.gui;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.vm.Program;
import org.ethereum.vm.ProgramInvokeFactory;
@ -31,7 +32,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
private Transaction tx;
public ProgramPlayDialog(Transaction tx) {
public ProgramPlayDialog(byte[] code, Transaction tx, Block lastBlock) {
this.tx = tx;
@ -46,8 +47,8 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
// byte[] codeBytes =
// Hex.decode(code);
Program program = new Program(tx.getData() ,
ProgramInvokeFactory.createProgramInvoke(tx, null));
Program program = new Program(code ,
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock));
program.addListener(this);
program.fullTrace();
@ -128,9 +129,9 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
* this method should be invoked from the
* event-dispatching thread.
*/
public static void createAndShowGUI(Transaction tx) {
public static void createAndShowGUI(byte[] runCode, Transaction tx, Block lastBlock) {
ProgramPlayDialog ppd = new ProgramPlayDialog(tx);
ProgramPlayDialog ppd = new ProgramPlayDialog(runCode, tx, lastBlock);
//Create and set up the window.
JFrame frame = new JFrame("Program Draft Play");

View File

@ -72,7 +72,11 @@ public class Program {
if (this.pc > ops.length) {
stop();
throw new RuntimeException("pc overflow pc: " + pc);
throw new RuntimeException("pc overflow pc= " + pc);
}
if (this.pc == ops.length) {
stop();
}
}
@ -386,8 +390,16 @@ public class Program {
globalOutput.append("\n HReturn: ").append(Hex.toHexString(result.gethReturn().array()));
}
// soffisticated assumption that msg.data != codedata
// means we are calling the contract not creating it
byte[] txData = invokeData.getDataCopy(DataWord.ZERO, getDataSize());
if (!Arrays.equals(txData, ops)){
globalOutput.append("\n msg.data: ").append(Hex.toHexString( txData ));
}
globalOutput.append("\n\n Spent Gas: ").append(result.getGasUsed());
if (listener != null){
listener.output(globalOutput.toString());
}