Skip to content
This repository was archived by the owner on Oct 28, 2021. It is now read-only.

Commit 5d8f676

Browse files
authored
Merge pull request #3597 from ethereum/eip86
EIP86
2 parents b228e53 + 83182ad commit 5d8f676

File tree

10 files changed

+84
-64
lines changed

10 files changed

+84
-64
lines changed

libdevcrypto/Common.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ bool dev::SignatureStruct::isValid() const noexcept
6565

6666
Address dev::ZeroAddress = Address();
6767

68+
Address dev::MaxAddress = Address("0xffffffffffffffffffffffffffffffffffffffff");
69+
6870
Public dev::toPublic(Secret const& _secret)
6971
{
7072
auto* ctx = getCtx();

libdevcrypto/Common.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ using Address = h160;
6464
/// The zero address.
6565
extern Address ZeroAddress;
6666

67+
/// The last address.
68+
extern Address MaxAddress;
69+
6770
/// A vector of Ethereum addresses.
6871
using Addresses = h160s;
6972

libethashseal/Ethash.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ void Ethash::verify(Strictness _s, BlockHeader const& _bi, BlockHeader const& _p
146146

147147
void Ethash::verifyTransaction(ImportRequirements::value _ir, TransactionBase const& _t, BlockHeader const& _bi) const
148148
{
149+
SealEngineFace::verifyTransaction(_ir, _t, _bi);
150+
149151
if (_ir & ImportRequirements::TransactionSignatures)
150152
{
151-
if (_bi.number() >= chainParams().u256Param("homsteadForkBlock"))
152-
_t.checkLowS();
153153
if (_bi.number() >= chainParams().u256Param("EIP158ForkBlock"))
154154
{
155155
int chainID(chainParams().u256Param("chainID"));

libethcore/Common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ enum class ImportResult
104104
AlreadyKnown,
105105
Malformed,
106106
OverbidGasPrice,
107-
BadChain
107+
BadChain,
108+
ZeroSignature
108109
};
109110

110111
struct ImportRequirements

libethcore/SealEngine.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ void SealEngineFace::populateFromParent(BlockHeader& _bi, BlockHeader const& _pa
4343
_bi.populateFromParent(_parent);
4444
}
4545

46-
void SealEngineFace::verifyTransaction(ImportRequirements::value _ir, TransactionBase const& _t, BlockHeader const&) const
46+
void SealEngineFace::verifyTransaction(ImportRequirements::value _ir, TransactionBase const& _t, BlockHeader const& _bi) const
4747
{
48-
if (_ir & ImportRequirements::TransactionSignatures)
48+
if ((_ir & ImportRequirements::TransactionSignatures) && _bi.number() < chainParams().u256Param("metropolisForkBlock") && _t.hasZeroSignature())
49+
BOOST_THROW_EXCEPTION(InvalidSignature());
50+
if (_bi.number() >= chainParams().u256Param("homsteadForkBlock") && (_ir & ImportRequirements::TransactionSignatures))
4951
_t.checkLowS();
5052
}
5153

libethcore/Transaction.cpp

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,29 @@ TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _check
7070
h256 r = rlp[field = 7].toInt<u256>();
7171
h256 s = rlp[field = 8].toInt<u256>();
7272

73-
if (v > 36)
74-
m_chainId = (v - 35) / 2;
75-
else if (v == 27 || v == 28)
76-
m_chainId = -4;
73+
m_vrs = SignatureStruct{ r, s, v };
74+
75+
if (hasZeroSignature())
76+
m_chainId = m_vrs.v;
7777
else
78-
BOOST_THROW_EXCEPTION(InvalidSignature());
78+
{
79+
if (v > 36)
80+
m_chainId = (v - 35) / 2;
81+
else if (v == 27 || v == 28)
82+
m_chainId = -4;
83+
else
84+
BOOST_THROW_EXCEPTION(InvalidSignature());
85+
m_vrs.v = v - (m_chainId * 2 + 35);
86+
87+
if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid())
88+
BOOST_THROW_EXCEPTION(InvalidSignature());
89+
}
7990

80-
v = v - (m_chainId * 2 + 35);
91+
if (_checkSig == CheckTransaction::Everything)
92+
m_sender = sender();
8193

8294
if (rlp.itemCount() > 9)
8395
BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("to many fields in the transaction RLP"));
84-
85-
m_vrs = SignatureStruct{ r, s, v };
86-
if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid())
87-
BOOST_THROW_EXCEPTION(InvalidSignature());
88-
if (_checkSig == CheckTransaction::Everything)
89-
m_sender = sender();
9096
}
9197
catch (Exception& _e)
9298
{
@@ -111,10 +117,15 @@ Address const& TransactionBase::sender() const
111117
{
112118
if (!m_sender)
113119
{
114-
auto p = recover(m_vrs, sha3(WithoutSignature));
115-
if (!p)
116-
BOOST_THROW_EXCEPTION(InvalidSignature());
117-
m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p))));
120+
if (hasZeroSignature())
121+
m_sender = MaxAddress;
122+
else
123+
{
124+
auto p = recover(m_vrs, sha3(WithoutSignature));
125+
if (!p)
126+
BOOST_THROW_EXCEPTION(InvalidSignature());
127+
m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p))));
128+
}
118129
}
119130
return m_sender;
120131
}

libethcore/Transaction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ class TransactionBase
142142
/// @returns the signature of the transaction. Encodes the sender.
143143
SignatureStruct const& signature() const { return m_vrs; }
144144

145+
bool hasZeroSignature() const { return !m_vrs.s && !m_vrs.r; }
146+
145147
void sign(Secret const& _priv); ///< Sign the transaction.
146148

147149
/// @returns amount of gas required for the basic payment.

libethereum/Executive.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -198,23 +198,26 @@ void Executive::initialize(Transaction const& _transaction)
198198
BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError((bigint)m_baseGasRequired, (bigint)m_t.gas()));
199199
}
200200

201-
// Avoid invalid transactions.
202-
u256 nonceReq;
203-
try
201+
if (!m_t.hasZeroSignature())
204202
{
205-
nonceReq = m_s.getNonce(m_t.sender());
206-
}
207-
catch (...)
208-
{
209-
clog(ExecutiveWarnChannel) << "Invalid Signature";
210-
m_excepted = TransactionException::InvalidSignature;
211-
throw;
212-
}
213-
if (m_t.nonce() != nonceReq)
214-
{
215-
clog(ExecutiveWarnChannel) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce();
216-
m_excepted = TransactionException::InvalidNonce;
217-
BOOST_THROW_EXCEPTION(InvalidNonce() << RequirementError((bigint)nonceReq, (bigint)m_t.nonce()));
203+
// Avoid invalid transactions.
204+
u256 nonceReq;
205+
try
206+
{
207+
nonceReq = m_s.getNonce(m_t.sender());
208+
}
209+
catch (InvalidSignature const& e)
210+
{
211+
clog(ExecutiveWarnChannel) << "Invalid Signature";
212+
m_excepted = TransactionException::InvalidSignature;
213+
throw;
214+
}
215+
if (m_t.nonce() != nonceReq)
216+
{
217+
clog(ExecutiveWarnChannel) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce();
218+
m_excepted = TransactionException::InvalidNonce;
219+
BOOST_THROW_EXCEPTION(InvalidNonce() << RequirementError((bigint)nonceReq, (bigint)m_t.nonce()));
220+
}
218221
}
219222

220223
// Avoid unaffordable transactions.

libethereum/TransactionQueue.cpp

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,34 +57,15 @@ TransactionQueue::~TransactionQueue()
5757

5858
ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, IfDropped _ik)
5959
{
60-
// Check if we already know this transaction.
61-
h256 h = sha3(_transactionRLP);
62-
63-
Transaction t;
64-
ImportResult ir;
60+
try
6561
{
66-
UpgradableGuard l(m_lock);
67-
68-
ir = check_WITH_LOCK(h, _ik);
69-
if (ir != ImportResult::Success)
70-
return ir;
71-
72-
try
73-
{
74-
// Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender.
75-
// If it doesn't work, the signature is bad.
76-
// The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction).
77-
t = Transaction(_transactionRLP, CheckTransaction::Everything);
78-
UpgradeGuard ul(l);
79-
// cdebug << "Importing" << t;
80-
ir = manageImport_WITH_LOCK(h, t);
81-
}
82-
catch (...)
83-
{
84-
return ImportResult::Malformed;
85-
}
62+
Transaction t = Transaction(_transactionRLP, CheckTransaction::Everything);
63+
return import(t, _ik);
64+
}
65+
catch (Exception const&)
66+
{
67+
return ImportResult::Malformed;
8668
}
87-
return ir;
8869
}
8970

9071
ImportResult TransactionQueue::check_WITH_LOCK(h256 const& _h, IfDropped _ik)
@@ -100,6 +81,8 @@ ImportResult TransactionQueue::check_WITH_LOCK(h256 const& _h, IfDropped _ik)
10081

10182
ImportResult TransactionQueue::import(Transaction const& _transaction, IfDropped _ik)
10283
{
84+
if (_transaction.hasZeroSignature())
85+
return ImportResult::ZeroSignature;
10386
// Check if we already know this transaction.
10487
h256 h = _transaction.sha3(WithSignature);
10588

test/libethereum/TransactionQueue.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ using namespace dev::test;
3131

3232
BOOST_FIXTURE_TEST_SUITE(TransactionQueueSuite, TestOutputHelper)
3333

34+
BOOST_AUTO_TEST_CASE(TransactionEIP86)
35+
{
36+
dev::eth::TransactionQueue txq;
37+
Address to = Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b");
38+
RLPStream streamRLP;
39+
streamRLP.appendList(9);
40+
streamRLP << 0 << 10 * szabo << 25000;
41+
streamRLP << to << 0 << bytes() << 0 << 0 << 0;
42+
Transaction tx0(streamRLP.out(), CheckTransaction::Everything);
43+
ImportResult result = txq.import(tx0);
44+
BOOST_CHECK(result == ImportResult::ZeroSignature);
45+
BOOST_CHECK(txq.knownTransactions().size() == 0);
46+
}
47+
3448
BOOST_AUTO_TEST_CASE(tqMaxNonce)
3549
{
3650
dev::eth::TransactionQueue txq;
@@ -59,7 +73,6 @@ BOOST_AUTO_TEST_CASE(tqMaxNonce)
5973
BOOST_CHECK(10 == txq.maxNonce(to));
6074
txq.import(tx2);
6175
BOOST_CHECK(10 == txq.maxNonce(to));
62-
6376
}
6477

6578
BOOST_AUTO_TEST_CASE(tqPriority)

0 commit comments

Comments
 (0)