From bb1ae30df92a201e31408120d4cd027aaa2a37b6 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Sat, 23 May 2015 08:59:40 +0200 Subject: [PATCH 1/4] add transact create --- eth/main.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 33d049843..88b9198a8 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1032,6 +1032,67 @@ int main(int argc, char** argv) else cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } + else if (c && cmd == "cretract") + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) + { + u256 amount; + u256 gasPrice; + u256 gas; + string sechex; + string sdata; + + iss >> amount >> gasPrice >> gas >> sechex >> sdata; + + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + + cnote << "Data:"; + cnote << sdata; + bytes data = dev::eth::parseData(sdata); + cnote << "Bytes:"; + string sbd = asString(data); + bytes bbd = asBytes(sbd); + stringstream ssbd; + ssbd << bbd; + cnote << ssbd.str(); + int ssize = sechex.length(); + u256 minGas = (u256)Transaction::gasRequired(data, 0); + if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else + { + try + { + Secret secret = h256(fromHex(sechex)); + c->submitTransaction(secret, amount, data, gas, gasPrice); + + //Address dest = h160(fromHex(hexAddr)); + //c->submitTransaction(secret, amount, dest, data, gas, gasPrice); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } + } + else + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; + } #if ETH_FATDB else if (c && cmd == "listcontracts") { From f78b6166d7a05fa6e01d6ad188456651f02e508d Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 9 Jun 2015 12:15:44 +0200 Subject: [PATCH 2/4] add eth(CLI) functionalities --- eth/main.cpp | 133 ++++++++++++++++++++++++++++++++++++++--- libdevcore/FixedHash.h | 2 +- libethereum/Client.h | 2 + 3 files changed, 129 insertions(+), 8 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 2162776ea..66e3a7ed3 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -84,15 +84,24 @@ void interactiveHelp() << " minestop Stops mining." << endl << " mineforce Forces mining, even when there are no transactions." << endl << " block Gives the current block height." << endl + << " blockhashfromnumber Gives the block hash with the givne number." << endl + << " numberfromblockhash Gives the block number with the given hash." << endl + << " blockqueue Gives the current block queue status." << endl + << " findblock Searches for the block in the blockchain and blockqueue." << endl + << " firstunknown Gives the first unknown block from the blockqueue." << endl + << " retryunknown retries to import all unknown blocks from the blockqueue." << endl << " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl << " newaccount Creates a new account with the given name." << endl << " transact Execute a given transaction." << endl + << " txcreate Execute a given contract creation transaction." << endl << " send Execute a given transaction with current secret." << endl << " contract Create a new contract with current secret." << endl << " peers List the peers that are connected" << endl #if ETH_FATDB || !ETH_TRUE << " listaccounts List the accounts on the network." << endl << " listcontracts List the contracts on the network." << endl + << " balanceat
Gives the balance of the given account." << endl + << " codeat
Gives the code of the given account." << endl #endif << " setsigningkey Set the address with which to sign transactions." << endl << " setaddress Set the coinbase (mining payout) address." << endl @@ -961,9 +970,85 @@ int main(int argc, char** argv) cout << "Current mining beneficiary:" << endl << beneficiary << endl; cout << "Current signing account:" << endl << signingKey << endl; } + else if (c && cmd == "blockhashfromnumber") + { + if (iss.peek() != -1) + { + unsigned number; + iss >> number; + cout << " hash of block: " << c->hashFromNumber(number).hex() << endl; + } + } + else if (c && cmd == "numberfromblockhash") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + h256 hash = h256(fromHex(stringHash)); + cout << " number of block: " << c->numberFromHash(hash) << endl; + } + } else if (c && cmd == "block") { - cout << "Current block: " <blockChain().details().number << endl; + cout << "Current block: " << c->blockChain().details().number << endl; + } + else if (c && cmd == "blockqueue") + { + cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl; + } + else if (c && cmd == "findblock") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + h256 hash = h256(fromHex(stringHash)); + + // search in blockchain + cout << "search in blockchain... " << endl; + try + { + cout << c->blockInfo(hash) << endl; + } + catch(Exception& _e) + { + cout << "block not in blockchain" << endl; + cout << boost::diagnostic_information(_e) << endl; + } + + cout << "search in blockqueue... " << endl; + + switch(c->blockQueue().blockStatus(hash)) + { + case QueueStatus::Ready: + cout << "Ready" << endl; + break; + case QueueStatus::UnknownParent: + cout << "UnknownParent" << endl; + break; + case QueueStatus::Bad: + cout << "Bad" << endl; + break; + case QueueStatus::Unknown: + cout << "Unknown" << endl; + break; + default: + cout << "invalid queueStatus" << endl; + } + } + else + cwarn << "Require parameter: findblock HASH"; + } + else if (c && cmd == "firstunknown") + { + cout << "first unknown blockhash: " << c->blockQueue().firstUnknown().hex() << endl; + } + else if (c && cmd == "retryunknown") + { + c->retryUnkonwn(); } else if (cmd == "peers") { @@ -1077,7 +1162,7 @@ int main(int argc, char** argv) else cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } - else if (c && cmd == "cretract") + else if (c && cmd == "txcreate") { auto const& bc =c->blockChain(); auto h = bc.currentHash(); @@ -1119,10 +1204,7 @@ int main(int argc, char** argv) try { Secret secret = h256(fromHex(sechex)); - c->submitTransaction(secret, amount, data, gas, gasPrice); - - //Address dest = h160(fromHex(hexAddr)); - //c->submitTransaction(secret, amount, dest, data, gas, gasPrice); + cout << " new contract address : " << c->submitTransaction(secret, amount, data, gas, gasPrice) << endl; } catch (BadHexCharacter& _e) { @@ -1136,7 +1218,7 @@ int main(int argc, char** argv) } } else - cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET INIT"; } #if ETH_FATDB else if (c && cmd == "listcontracts") @@ -1161,6 +1243,43 @@ int main(int argc, char** argv) cout << ss << endl; } } + else if (c && cmd == "balanceat") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + Address address = h160(fromHex(stringHash)); + + cout << "balance of " << stringHash << " is: " << toString(c->balanceAt(address)) << endl; + } + } + // TODO implement << operator for std::unorderd_map +// else if (c && cmd == "storageat") +// { +// if (iss.peek() != -1) +// { +// string stringHash; +// iss >> stringHash; + +// Address address = h160(fromHex(stringHash)); + +// cout << "storage at " << stringHash << " is: " << c->storageAt(address) << endl; +// } +// } + else if (c && cmd == "codeat") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + Address address = h160(fromHex(stringHash)); + + cout << "code at " << stringHash << " is: " << toHex(c->codeAt(address)) << endl; + } + } #endif else if (c && cmd == "send") { diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 9b25837af..88bc0fe95 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -113,7 +113,7 @@ public: /// @returns an abridged version of the hash as a user-readable hex string. std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; } - /// @returns an abridged version of the hash as a user-readable hex string. + /// @returns the hash as a user-readable hex string. std::string hex() const { return toHex(ref()); } /// @returns a mutable byte vector_ref to the object's data. diff --git a/libethereum/Client.h b/libethereum/Client.h index 5132b5a30..90200c20b 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -156,6 +156,8 @@ public: CanonBlockChain const& blockChain() const { return m_bc; } /// Get some information on the block queue. BlockQueueStatus blockQueueStatus() const { return m_bq.status(); } + /// Get the block queue. + BlockQueue const& blockQueue() const { return m_bq; } // Mining stuff: From af9c64da917ff7b65f36faf4bfd298a0cb339b7e Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 9 Jun 2015 14:10:18 +0200 Subject: [PATCH 3/4] add queuestatus::importing --- eth/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 66e3a7ed3..8b3e1fa78 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1026,6 +1026,9 @@ int main(int argc, char** argv) case QueueStatus::Ready: cout << "Ready" << endl; break; + case QueueStatus::Importing: + cout << "Importing" << endl; + break; case QueueStatus::UnknownParent: cout << "UnknownParent" << endl; break; From 43f8d638fbe5bd3842fe8ace3656cdf8e5b12e54 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 11 Jun 2015 13:05:58 +0200 Subject: [PATCH 4/4] add transactnonce to ethcli --- eth/main.cpp | 70 ++++++++++++++++++++++++++++++++++++++ libethereum/ClientBase.cpp | 15 ++++++++ libethereum/ClientBase.h | 1 + 3 files changed, 86 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 8b3e1fa78..9128d9391 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -93,6 +93,7 @@ void interactiveHelp() << " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl << " newaccount Creates a new account with the given name." << endl << " transact Execute a given transaction." << endl + << " transactnonce Execute a given transaction with a specified nonce." << endl << " txcreate Execute a given contract creation transaction." << endl << " send Execute a given transaction with current secret." << endl << " contract Create a new contract with current secret." << endl @@ -1165,6 +1166,75 @@ int main(int argc, char** argv) else cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } + + else if (c && cmd == "transactnonce") + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) + { + string hexAddr; + u256 amount; + u256 gasPrice; + u256 gas; + string sechex; + string sdata; + u256 nonce; + + iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata >> nonce; + + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + + cnote << "Data:"; + cnote << sdata; + bytes data = dev::eth::parseData(sdata); + cnote << "Bytes:"; + string sbd = asString(data); + bytes bbd = asBytes(sbd); + stringstream ssbd; + ssbd << bbd; + cnote << ssbd.str(); + int ssize = sechex.length(); + int size = hexAddr.length(); + u256 minGas = (u256)Transaction::gasRequired(data, 0); + if (size < 40) + { + if (size > 0) + cwarn << "Invalid address length:" << size; + } + else if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else + { + try + { + Secret secret = h256(fromHex(sechex)); + Address dest = h160(fromHex(hexAddr)); + c->submitTransaction(secret, amount, dest, data, gas, gasPrice, nonce); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } + } + else + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA NONCE"; + } + else if (c && cmd == "txcreate") { auto const& bc =c->blockChain(); diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 8dc666bb5..19f0fe737 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -45,6 +45,21 @@ State ClientBase::asOf(BlockNumber _h) const return asOf(bc().numberHash(_h)); } +void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce) +{ + prepareForTransaction(); + + auto a = toAddress(_secret); + u256 n = postMine().transactionsFrom(a); + cdebug << "submitTx: " << a << "postMine=" << n << "; tq=" << m_tq.maxNonce(a); + + Transaction t(_value, _gasPrice, _gas, _dest, _data, _nonce, _secret); + m_tq.import(t.rlp()); + + StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); + cnote << "New transaction " << t << "(maxNonce for sender" << a << "is" << m_tq.maxNonce(a) << ")"; +} + void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) { prepareForTransaction(); diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 2b271b1df..19bb2088d 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -76,6 +76,7 @@ public: virtual ~ClientBase() {} /// Submits the given message-call transaction. + virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce); virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; /// Submits a new contract-creation transaction.