Skip to content

Commit 2d8b682

Browse files
GagziWcburgdorf
authored andcommitted
creation of a DoSContract: deploy empty contract/ sstore / revert sstore / revert empty contract deployment and adjusted and added the respective benchmark
casing and naming issues fixed + empty implementation issues fixed fixed typo, deleted unnecessary initialization, increased tx per block, decreased block number
1 parent 3d186e5 commit 2d8b682

File tree

6 files changed

+357
-6
lines changed

6 files changed

+357
-6
lines changed
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
from abc import (
2+
abstractmethod
3+
)
4+
5+
import logging
6+
import pathlib
7+
8+
from typing import (
9+
Tuple
10+
)
11+
from eth_utils import (
12+
encode_hex,
13+
decode_hex,
14+
)
15+
from web3 import (
16+
Web3
17+
)
18+
from eth.chains.base import (
19+
MiningChain,
20+
)
21+
from eth.constants import (
22+
CREATE_CONTRACT_ADDRESS
23+
)
24+
from eth.rlp.blocks import (
25+
BaseBlock,
26+
)
27+
from utils.chain_plumbing import (
28+
FUNDED_ADDRESS,
29+
FUNDED_ADDRESS_PRIVATE_KEY,
30+
get_all_chains,
31+
)
32+
from utils.compile import (
33+
get_compiled_contract
34+
)
35+
from utils.reporting import (
36+
DefaultStat,
37+
)
38+
from utils.tx import (
39+
new_transaction,
40+
)
41+
from .base_benchmark import (
42+
BaseBenchmark,
43+
)
44+
45+
FIRST_TX_GAS_LIMIT = 367724
46+
SECOND_TX_GAS_LIMIT = 62050
47+
THIRD_TX_GAS_LIMIT = 104789
48+
FORTH_TX_GAS_LIMIT = 21272
49+
FIFTH_TX_GAS_LIMIT = 21272
50+
51+
CONTRACT_FILE = 'scripts/benchmark/contract_data/DOSContract.sol'
52+
CONTRACT_NAME = 'DOSContract'
53+
54+
W3_TX_DEFAULTS = {'gas': 0, 'gasPrice': 0}
55+
56+
57+
class BaseDOSContractBenchmark(BaseBenchmark):
58+
59+
def __init__(self, num_blocks: int = 20, num_tx: int = 10) -> None:
60+
super().__init__()
61+
62+
self.num_blocks = num_blocks
63+
self.num_tx = num_tx
64+
65+
self.contract_interface = get_compiled_contract(
66+
pathlib.Path(CONTRACT_FILE),
67+
CONTRACT_NAME
68+
)
69+
70+
self.w3 = Web3()
71+
72+
def _setup_benchmark(self, chain: MiningChain) -> None:
73+
"""
74+
This hook can be overwritten to perform preparations on the chain
75+
that do not count into the measured benchmark time
76+
"""
77+
pass
78+
79+
@abstractmethod
80+
def _apply_transaction(self, chain: MiningChain) -> None:
81+
raise NotImplementedError(
82+
"Must be implemented by subclasses"
83+
)
84+
85+
def execute(self) -> DefaultStat:
86+
total_stat = DefaultStat()
87+
88+
for chain in get_all_chains():
89+
90+
self._setup_benchmark(chain)
91+
92+
value = self.as_timed_result(
93+
lambda: self.mine_blocks(chain, self.num_blocks, self.num_tx)
94+
)
95+
96+
total_gas_used, total_num_tx = value.wrapped_value
97+
98+
stat = DefaultStat(
99+
caption=chain.get_vm().fork,
100+
total_blocks=self.num_blocks,
101+
total_tx=total_num_tx,
102+
total_seconds=value.duration,
103+
total_gas=total_gas_used,
104+
)
105+
total_stat = total_stat.cumulate(stat)
106+
self.print_stat_line(stat)
107+
108+
return total_stat
109+
110+
def mine_blocks(self, chain: MiningChain, num_blocks: int, num_tx: int) -> Tuple[int, int]:
111+
total_gas_used = 0
112+
total_num_tx = 0
113+
114+
blocks = tuple(self.mine_block(chain, i, num_tx) for i in range(1, num_blocks + 1))
115+
total_gas_used = sum(block.header.gas_used for block in blocks)
116+
total_num_tx = sum(len(block.transactions) for block in blocks)
117+
118+
return total_gas_used, total_num_tx
119+
120+
def mine_block(self,
121+
chain: MiningChain,
122+
block_number: int,
123+
num_tx: int) -> BaseBlock:
124+
125+
for i in range(1, num_tx + 1):
126+
self._apply_transaction(chain)
127+
128+
return chain.mine_block()
129+
130+
def deploy_dos_contract(self, chain: MiningChain) -> None:
131+
# Instantiate the contract
132+
dos_contract = self.w3.eth.contract(
133+
abi=self.contract_interface['abi'],
134+
bytecode=self.contract_interface['bin']
135+
)
136+
137+
# Build transaction to deploy the contract
138+
w3_tx1 = dos_contract.constructor().buildTransaction(W3_TX_DEFAULTS)
139+
140+
tx = new_transaction(
141+
vm=chain.get_vm(),
142+
private_key=FUNDED_ADDRESS_PRIVATE_KEY,
143+
from_=FUNDED_ADDRESS,
144+
to=CREATE_CONTRACT_ADDRESS,
145+
amount=0,
146+
gas=FIRST_TX_GAS_LIMIT,
147+
data=decode_hex(w3_tx1['data']),
148+
)
149+
150+
logging.debug('Applying Transaction {}'.format(tx))
151+
152+
block, receipt, computation = chain.apply_transaction(tx)
153+
self.deployed_contract_address = computation.msg.storage_address
154+
155+
assert computation.is_success
156+
157+
# Interact with the deployed contract by calling the totalSupply() API ?????
158+
self.dos_contract = self.w3.eth.contract(
159+
address=Web3.toChecksumAddress(encode_hex(self.deployed_contract_address)),
160+
abi=self.contract_interface['abi'],
161+
)
162+
163+
def sstore_uint64(self, chain: MiningChain) -> None:
164+
w3_tx2 = self.dos_contract.functions.storageEntropy().buildTransaction(W3_TX_DEFAULTS)
165+
166+
tx2 = new_transaction(
167+
vm=chain.get_vm(),
168+
private_key=FUNDED_ADDRESS_PRIVATE_KEY,
169+
from_=FUNDED_ADDRESS,
170+
to=self.deployed_contract_address,
171+
amount=0,
172+
gas=SECOND_TX_GAS_LIMIT,
173+
data=decode_hex(w3_tx2['data']),
174+
)
175+
176+
block, receipt, computation = chain.apply_transaction(tx2)
177+
178+
assert computation.is_success
179+
180+
def create_empty_contract(self, chain: MiningChain) -> None:
181+
w3_tx3 = self.dos_contract.functions.createEmptyContract().buildTransaction(W3_TX_DEFAULTS)
182+
183+
tx3 = new_transaction(
184+
vm=chain.get_vm(),
185+
private_key=FUNDED_ADDRESS_PRIVATE_KEY,
186+
from_=FUNDED_ADDRESS,
187+
to=self.deployed_contract_address,
188+
amount=0,
189+
gas=THIRD_TX_GAS_LIMIT,
190+
data=decode_hex(w3_tx3['data']),
191+
)
192+
193+
block, receipt, computation = chain.apply_transaction(tx3)
194+
195+
assert computation.is_success
196+
197+
def sstore_uint64_revert(self, chain: MiningChain) -> None:
198+
w3_tx4 = self.dos_contract.functions.storageEntropyRevert().buildTransaction(W3_TX_DEFAULTS)
199+
200+
tx4 = new_transaction(
201+
vm=chain.get_vm(),
202+
private_key=FUNDED_ADDRESS_PRIVATE_KEY,
203+
from_=FUNDED_ADDRESS,
204+
to=self.deployed_contract_address,
205+
amount=0,
206+
gas=FORTH_TX_GAS_LIMIT,
207+
data=decode_hex(w3_tx4['data']),
208+
)
209+
210+
block, receipt, computation = chain.apply_transaction(tx4)
211+
212+
def create_empty_contract_revert(self, chain: MiningChain) -> None:
213+
w3_tx5 = self.dos_contract.functions.createEmptyContractRevert().buildTransaction(
214+
W3_TX_DEFAULTS)
215+
216+
tx5 = new_transaction(
217+
vm=chain.get_vm(),
218+
private_key=FUNDED_ADDRESS_PRIVATE_KEY,
219+
from_=FUNDED_ADDRESS,
220+
to=self.deployed_contract_address,
221+
amount=0,
222+
gas=FIFTH_TX_GAS_LIMIT,
223+
data=decode_hex(w3_tx5['data']),
224+
)
225+
226+
block, receipt, computation = chain.apply_transaction(tx5)
227+
228+
229+
class DOSContractDeployBenchmark(BaseDOSContractBenchmark):
230+
231+
@property
232+
def name(self) -> str:
233+
return 'DOSContract deployment'
234+
235+
def _apply_transaction(self, chain: MiningChain) -> None:
236+
self.deploy_dos_contract(chain)
237+
238+
239+
class DOSContractSstoreUint64Benchmark(BaseDOSContractBenchmark):
240+
241+
@property
242+
def name(self) -> str:
243+
return 'DOSContract sstore uint64'
244+
245+
def _setup_benchmark(self, chain: MiningChain) -> None:
246+
self.deploy_dos_contract(chain)
247+
chain.mine_block()
248+
249+
def _apply_transaction(self, chain: MiningChain) -> None:
250+
self.sstore_uint64(chain)
251+
252+
253+
class DOSContractCreateEmptyContractBenchmark(BaseDOSContractBenchmark):
254+
255+
@property
256+
def name(self) -> str:
257+
return 'DOSContract empty contract deployment'
258+
259+
def _setup_benchmark(self, chain: MiningChain) -> None:
260+
self.deploy_dos_contract(chain)
261+
chain.mine_block()
262+
263+
def _apply_transaction(self, chain: MiningChain) -> None:
264+
self.create_empty_contract(chain)
265+
266+
267+
class DOSContractRevertSstoreUint64Benchmark(BaseDOSContractBenchmark):
268+
269+
@property
270+
def name(self) -> str:
271+
return 'DOSContract revert empty sstore uint64'
272+
273+
def _setup_benchmark(self, chain: MiningChain) -> None:
274+
self.deploy_dos_contract(chain)
275+
chain.mine_block()
276+
277+
def _apply_transaction(self, chain: MiningChain) -> None:
278+
self.sstore_uint64_revert(chain)
279+
280+
281+
class DOSContractRevertCreateEmptyContractBenchmark(BaseDOSContractBenchmark):
282+
283+
@property
284+
def name(self) -> str:
285+
return 'DOScontract revert contract deployment'
286+
287+
def _setup_benchmark(self, chain: MiningChain) -> None:
288+
self.deploy_dos_contract(chain)
289+
chain.mine_block()
290+
291+
def _apply_transaction(self, chain: MiningChain) -> None:
292+
self.create_empty_contract_revert(chain)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
pragma solidity ^0.4.23;
2+
3+
contract DOSContract{
4+
address[] deployedContracts;
5+
uint64[] liste;
6+
7+
function createEmptyContract() public{
8+
address newContract = new EmptyContract();
9+
deployedContracts.push(newContract);
10+
}
11+
12+
function storageEntropy() public{
13+
liste.push(1);
14+
}
15+
16+
function storageEntropyRevert() public{
17+
liste.push(1);
18+
revert("Error");
19+
}
20+
21+
function createEmptyContractRevert() public{
22+
address newContract = new EmptyContract();
23+
deployedContracts.push(newContract);
24+
revert();
25+
}
26+
}
27+
28+
contract EmptyContract{
29+
30+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"contracts" :
3+
{
4+
"scripts/benchmark/contract_data/DOSContract.sol:DOSContract" :
5+
{
6+
"abi" : "[{\"constant\":false,\"inputs\":[],\"name\":\"createEmptyContract\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"storageEntropy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"createEmptyContractRevert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"storageEntropyRevert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
7+
"bin" : "608060405234801561001057600080fd5b50610398806100206000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631c138fb114610067578063411426dc1461007e5780634660963914610095578063ae30a51f146100ac575b600080fd5b34801561007357600080fd5b5061007c6100c3565b005b34801561008a57600080fd5b50610093610155565b005b3480156100a157600080fd5b506100aa6101b0565b005b3480156100b857600080fd5b506100c1610244565b005b60006100cd61030b565b604051809103906000f0801580156100e9573d6000803e3d6000fd5b50905060008190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600180908060018154018082558091505090600182039060005260206000209060049182820401919006600802909192909190916101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60006101ba61030b565b604051809103906000f0801580156101d6573d6000803e3d6000fd5b50905060008190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600080fd5b600180908060018154018082558091505090600182039060005260206000209060049182820401919006600802909192909190916101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f4572726f7200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60405160528061031b8339019056006080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a72305820380024be49f6252eb658404f967733d0f5dedd55afadb0907757472a1dfc3a110029a165627a7a72305820ea75b78be833699c8aaaa51d54faf1aaed3f9b4bc0d11ff36a8791b45a17dd760029"
8+
},
9+
"scripts/benchmark/contract_data/DOSContract.sol:EmptyContract" :
10+
{
11+
"abi" : "[]",
12+
"bin" : "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a72305820380024be49f6252eb658404f967733d0f5dedd55afadb0907757472a1dfc3a110029"
13+
}
14+
},
15+
"version" : "0.4.25-develop.2018.6.6+commit.59b35fa5.Linux.g++"
16+
}

scripts/benchmark/contract_data/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
CONTRACTS_ROOT = "./scripts/benchmark/contract_data/"
66

77
CONTRACTS = [
8-
"erc20.sol"
8+
"erc20.sol",
9+
"DOSContract.sol"
910
]
1011

1112

0 commit comments

Comments
 (0)