Contract Call Dialog:
+ Play button to call already saved contracts
This commit is contained in:
parent
a9b890a86d
commit
9ae78521a6
|
@ -1,8 +1,10 @@
|
||||||
package org.ethereum.gui;
|
package org.ethereum.gui;
|
||||||
|
|
||||||
import org.ethereum.core.Account;
|
import org.ethereum.core.Account;
|
||||||
|
import org.ethereum.core.AccountState;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.manager.MainData;
|
import org.ethereum.manager.MainData;
|
||||||
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.ethereum.net.client.ClientPeer;
|
import org.ethereum.net.client.ClientPeer;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.ethereum.util.Utils;
|
import org.ethereum.util.Utils;
|
||||||
|
@ -32,7 +34,7 @@ import java.util.Collection;
|
||||||
*/
|
*/
|
||||||
class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
||||||
|
|
||||||
Logger logger = LoggerFactory.getLogger(getClass());
|
Logger logger = LoggerFactory.getLogger("ui");
|
||||||
|
|
||||||
|
|
||||||
ContractCallDialog dialog;
|
ContractCallDialog dialog;
|
||||||
|
@ -79,6 +81,24 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
||||||
rejectLabel.setToolTipText("Cancel");
|
rejectLabel.setToolTipText("Cancel");
|
||||||
rejectLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
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("");
|
JLabel statusMessage = new JLabel("");
|
||||||
statusMessage.setBounds(50, 360, 400, 50);
|
statusMessage.setBounds(50, 360, 400, 50);
|
||||||
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
@ -178,6 +198,29 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
||||||
this.setResizable(false);
|
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() {
|
protected JRootPane createRootPane() {
|
||||||
|
|
||||||
Container parent = this.getParent();
|
Container parent = this.getParent();
|
||||||
|
@ -223,9 +266,28 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
||||||
return;
|
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(",");
|
Object[] lexaList = msgDataTA.getText().split(",");
|
||||||
byte[] data = ByteUtil.encodeDataList(lexaList);
|
data = ByteUtil.encodeDataList(lexaList);
|
||||||
|
} else {
|
||||||
|
data = new byte[]{};
|
||||||
|
}
|
||||||
|
|
||||||
byte[] contractAddress = Hex.decode( contractAddrInput.getText());
|
byte[] contractAddress = Hex.decode( contractAddrInput.getText());
|
||||||
|
|
||||||
|
@ -252,23 +314,18 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
||||||
Transaction tx = new Transaction(nonce, gasPrice, gasValue,
|
Transaction tx = new Transaction(nonce, gasPrice, gasValue,
|
||||||
contractAddress, endowment, data);
|
contractAddress, endowment, data);
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("tx.hash: {}", (new BigInteger(tx.getHash()).toString(16)));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tx.sign(senderPrivKey);
|
tx.sign(senderPrivKey);
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
|
|
||||||
dialog.alertStatusMsg("Failed to sign the transaction");
|
dialog.alertStatusMsg("Failed to sign the transaction");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwingWorker
|
return tx;
|
||||||
DialogWorker worker = new DialogWorker(tx, this);
|
|
||||||
worker.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class AccountWrapper {
|
public class AccountWrapper {
|
||||||
|
|
||||||
private Account account;
|
private Account account;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.ethereum.core.Account;
|
||||||
import org.ethereum.core.AccountState;
|
import org.ethereum.core.AccountState;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.manager.MainData;
|
import org.ethereum.manager.MainData;
|
||||||
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.ethereum.net.client.ClientPeer;
|
import org.ethereum.net.client.ClientPeer;
|
||||||
import org.ethereum.util.Utils;
|
import org.ethereum.util.Utils;
|
||||||
import org.spongycastle.util.BigIntegers;
|
import org.spongycastle.util.BigIntegers;
|
||||||
|
@ -107,7 +108,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
|
||||||
}
|
}
|
||||||
contractAddrInput.setText(Hex.toHexString(tx.getContractAddress()));
|
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();
|
Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount();
|
||||||
BigInteger currentBalance = account.getState().getBalance();
|
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());
|
BigInteger gasInput = new BigInteger( this.gasInput.getText());
|
||||||
|
|
||||||
boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0;
|
boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.ethereum.gui;
|
package org.ethereum.gui;
|
||||||
|
|
||||||
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.vm.Program;
|
import org.ethereum.vm.Program;
|
||||||
import org.ethereum.vm.ProgramInvokeFactory;
|
import org.ethereum.vm.ProgramInvokeFactory;
|
||||||
|
@ -31,7 +32,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||||
|
|
||||||
private Transaction tx;
|
private Transaction tx;
|
||||||
|
|
||||||
public ProgramPlayDialog(Transaction tx) {
|
public ProgramPlayDialog(byte[] code, Transaction tx, Block lastBlock) {
|
||||||
|
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
|
|
||||||
|
@ -46,8 +47,8 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||||
// byte[] codeBytes =
|
// byte[] codeBytes =
|
||||||
// Hex.decode(code);
|
// Hex.decode(code);
|
||||||
|
|
||||||
Program program = new Program(tx.getData() ,
|
Program program = new Program(code ,
|
||||||
ProgramInvokeFactory.createProgramInvoke(tx, null));
|
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock));
|
||||||
|
|
||||||
program.addListener(this);
|
program.addListener(this);
|
||||||
program.fullTrace();
|
program.fullTrace();
|
||||||
|
@ -128,9 +129,9 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||||
* this method should be invoked from the
|
* this method should be invoked from the
|
||||||
* event-dispatching thread.
|
* 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.
|
//Create and set up the window.
|
||||||
JFrame frame = new JFrame("Program Draft Play");
|
JFrame frame = new JFrame("Program Draft Play");
|
||||||
|
|
|
@ -72,7 +72,11 @@ public class Program {
|
||||||
|
|
||||||
if (this.pc > ops.length) {
|
if (this.pc > ops.length) {
|
||||||
stop();
|
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()));
|
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());
|
globalOutput.append("\n\n Spent Gas: ").append(result.getGasUsed());
|
||||||
|
|
||||||
|
|
||||||
if (listener != null){
|
if (listener != null){
|
||||||
listener.output(globalOutput.toString());
|
listener.output(globalOutput.toString());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue