Browse Source

Documentation for Transaction.

cl-refactor
Gav Wood 10 years ago
parent
commit
ef1c4d7967
  1. 8
      libethereum/Transaction.cpp
  2. 92
      libethereum/Transaction.h
  3. 4
      test/crypto.cpp
  4. 2
      test/vm.cpp

8
libethereum/Transaction.cpp

@ -71,7 +71,7 @@ Address Transaction::sender() const
{
if (!m_sender)
{
auto p = recover(*(Signature const*)&m_vrs, sha3(false));
auto p = recover(*(Signature const*)&m_vrs, sha3(WithoutSignature));
if (!p)
BOOST_THROW_EXCEPTION(InvalidSignature());
m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p))));
@ -81,12 +81,14 @@ Address Transaction::sender() const
void Transaction::sign(Secret _priv)
{
auto sig = dev::sign(_priv, sha3(false));
auto sig = dev::sign(_priv, sha3(WithoutSignature));
m_vrs = *(SignatureStruct const*)&sig;
}
void Transaction::streamRLP(RLPStream& _s, bool _sig) const
void Transaction::streamRLP(RLPStream& _s, IncludeSignature _sig) const
{
if (m_type == NullTransaction)
return;
_s.appendList((_sig ? 3 : 0) + 6);
_s << m_nonce << m_gasPrice << m_gas;
if (m_type == MessageCall)

92
libethereum/Transaction.h

@ -30,52 +30,104 @@ namespace dev
namespace eth
{
/// Named-boolean type to encode whether a signature be included in the serialisation process.
enum IncludeSignature
{
WithoutSignature = 0, ///< Do not include a signature.
WithSignature = 1, ///< Do include a signature.
};
/// Encodes a transaction, ready to be exported to or freshly imported from RLP.
class Transaction
{
public:
enum Type
{
NullTransaction,
ContractCreation,
MessageCall
};
/// Constructs a null transaction.
Transaction() {}
/// Constructs a signed message-call transaction.
Transaction(u256 _value, u256 _gasPrice, u256 _gas, Address const& _dest, bytes const& _data, u256 _nonce, Secret const& _secret): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); }
/// Constructs a signed contract-creation transaction.
Transaction(u256 _value, u256 _gasPrice, u256 _gas, bytes const& _data, u256 _nonce, Secret const& _secret): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); }
/// Constructs an unsigned message-call transaction.
Transaction(u256 _value, u256 _gasPrice, u256 _gas, Address const& _dest, bytes const& _data): m_type(MessageCall), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {}
/// Constructs an unsigned contract-creation transaction.
Transaction(u256 _value, u256 _gasPrice, u256 _gas, bytes const& _data): m_type(ContractCreation), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {}
/// Constructs a transaction from the given RLP.
Transaction(bytesConstRef _rlp, bool _checkSender = false);
/// Constructs a transaction from the given RLP.
Transaction(bytes const& _rlp, bool _checkSender = false): Transaction(&_rlp, _checkSender) {}
/// Checks equality of transactions.
bool operator==(Transaction const& _c) const { return m_type == _c.m_type && (m_type == ContractCreation || m_receiveAddress == _c.m_receiveAddress) && m_value == _c.m_value && m_data == _c.m_data; }
/// Checks inequality of transactions.
bool operator!=(Transaction const& _c) const { return !operator==(_c); }
Address safeSender() const noexcept; ///< Like sender() but will never throw. @returns a null Address if the signature is invalid.
Address sender() const; ///< Determine the sender of the transaction from the signature (and hash).
/// @returns sender of the transaction from the signature (and hash).
Address sender() const;
/// Like sender() but will never throw. @returns a null Address if the signature is invalid.
Address safeSender() const noexcept;
/// @returns true if transaction is non-null.
operator bool() const { return m_type != NullTransaction; }
/// @returns true if transaction is contract-creation.
bool isCreation() const { return m_type == ContractCreation; }
void streamRLP(RLPStream& _s, bool _sig = true) const;
/// @returns true if transaction is message-call.
bool isMessageCall() const { return m_type == MessageCall; }
bytes rlp(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return s.out(); }
std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); }
h256 sha3(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3(s.out()); }
bytes sha3Bytes(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3Bytes(s.out()); }
/// Serialises this transaction to an RLPStream.
void streamRLP(RLPStream& _s, IncludeSignature _sig = WithSignature) const;
Type type() const { return m_type; }
u256 nonce() const { return m_nonce; }
/// @returns the RLP serialisation of this transaction.
bytes rlp(IncludeSignature _sig = WithSignature) const { RLPStream s; streamRLP(s, _sig); return s.out(); }
/// @returns the SHA3 hash of the RLP serialisation of this transaction.
h256 sha3(IncludeSignature _sig = WithSignature) const { RLPStream s; streamRLP(s, _sig); return dev::sha3(s.out()); }
/// @returns the amount of ETH to be transferred by this (message-call) transaction, in Wei. Synonym for endowment().
u256 value() const { return m_value; }
Address receiveAddress() const { return m_receiveAddress; }
/// @returns the amount of ETH to be endowed by this (contract-creation) transaction, in Wei. Synonym for value().
u256 endowment() const { return m_value; }
/// @returns the base fee and thus the implied exchange rate of ETH to GAS.
u256 gasPrice() const { return m_gasPrice; }
/// @returns the total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended.
u256 gas() const { return m_gas; }
/// @returns the receiving address of the message-call transaction (undefined for contract-creation transactions).
Address receiveAddress() const { return m_receiveAddress; }
/// @returns the data associated with this (message-call) transaction. Synonym for initCode().
bytes const& data() const { return m_data; }
/// @returns the initialisation code associated with this (contract-creation) transaction. Synonym for data().
bytes const& initCode() const { return m_data; }
/// @returns the transaction-count of the sender.
u256 nonce() const { return m_nonce; }
/// @returns the signature of the transaction. Encodes the sender.
SignatureStruct const& signature() const { return m_vrs; }
private:
/// Type of transaction.
enum Type
{
NullTransaction, ///< Null transaction.
ContractCreation, ///< Transaction to create contracts - receiveAddress() is ignored.
MessageCall ///< Transaction to invoke a message call - receiveAddress() is used.
};
void sign(Secret _priv); ///< Sign the transaction.
Type m_type = NullTransaction; ///< True if this is a contract-creation transaction. F
Type m_type = NullTransaction; ///< Is this a contract-creation transaction or a message-call transaction?
u256 m_nonce; ///< The transaction-count of the sender.
u256 m_value; ///< The amount of ETH to be transferred by this transaction. Called 'endowment' for contract-creation transactions.
Address m_receiveAddress; ///< The receiving address of the transaction.
@ -84,11 +136,13 @@ private:
bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
SignatureStruct m_vrs; ///< The signature of the transaction. Encodes the sender.
mutable Address m_sender;
mutable Address m_sender; ///< Cached sender, determined from signature.
};
/// Nice name for vector of Transaction.
using Transactions = std::vector<Transaction>;
/// Simple human-readable stream-shift operator.
inline std::ostream& operator<<(std::ostream& _out, Transaction const& _t)
{
_out << "{";

4
test/crypto.cpp

@ -397,8 +397,8 @@ int cryptoTest()
auto msg = t.rlp(false);
cout << "TX w/o SIG: " << RLP(msg) << endl;
cout << "RLP(TX w/o SIG): " << toHex(t.rlpString(false)) << endl;
std::string hmsg = sha3(t.rlpString(false), false);
cout << "RLP(TX w/o SIG): " << toHex(t.rlp(false)) << endl;
std::string hmsg = sha3(t.rlp(false), false);
cout << "SHA256(RLP(TX w/o SIG)): 0x" << toHex(hmsg) << endl;
bytes privkey = sha3Bytes("123");

2
test/vm.cpp

@ -375,7 +375,7 @@ mArray FakeExtVM::exportCallCreates()
for (Transaction const& tx: callcreates)
{
mObject o;
o["destination"] = tx.type() == Transaction::ContractCreation ? "" : toString(tx.receiveAddress());
o["destination"] = tx.isCreation() ? "" : toString(tx.receiveAddress());
push(o, "gasLimit", tx.gas());
push(o, "value", tx.value());
o["data"] = "0x" + toHex(tx.data());

Loading…
Cancel
Save