17
17
package core
18
18
19
19
import (
20
+ "errors"
20
21
"math/big"
21
22
23
+ "github.com/ethereum/go-ethereum/common"
22
24
"github.com/ethereum/go-ethereum/core/state"
23
25
"github.com/ethereum/go-ethereum/core/types"
24
26
"github.com/ethereum/go-ethereum/core/vm"
@@ -28,8 +30,25 @@ import (
28
30
)
29
31
30
32
var (
31
- big8 = big .NewInt (8 )
32
- big32 = big .NewInt (32 )
33
+ big8 = big .NewInt (8 )
34
+ big32 = big .NewInt (32 )
35
+ blockedCodeHashErr = errors .New ("core: blocked code-hash found during execution" )
36
+
37
+ // DAO attack chain rupture mechanism
38
+ DAOSoftFork bool // Flag whether to vote for DAO rupture
39
+
40
+ ruptureBlock = uint64 (1800000 ) // Block number of the voted soft fork
41
+ ruptureTarget = big .NewInt (3141592 ) // Gas target (hard) for miners voting to fork
42
+ ruptureThreshold = big .NewInt (4000000 ) // Gas threshold for passing a fork vote
43
+ ruptureGasCache = make (map [common.Hash ]* big.Int ) // Amount of gas in the point of rupture
44
+ ruptureCodeHashes = map [common.Hash ]struct {}{
45
+ common .HexToHash ("6a5d24750f78441e56fec050dc52fe8e911976485b7472faac7464a176a67caa" ): struct {}{},
46
+ }
47
+ ruptureWhitelist = map [common.Address ]bool {
48
+ common .HexToAddress ("Da4a4626d3E16e094De3225A751aAb7128e96526" ): true , // multisig
49
+ common .HexToAddress ("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334" ): true , // attack contract
50
+ }
51
+ ruptureCacheLimit = 30000 // 1 epoch, 0.5 per possible fork
33
52
)
34
53
35
54
// StateProcessor is a basic Processor, which takes care of transitioning
@@ -86,11 +105,56 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
86
105
// ApplyTransactions returns the generated receipts and vm logs during the
87
106
// execution of the state transition phase.
88
107
func ApplyTransaction (config * ChainConfig , bc * BlockChain , gp * GasPool , statedb * state.StateDB , header * types.Header , tx * types.Transaction , usedGas * big.Int , cfg vm.Config ) (* types.Receipt , vm.Logs , * big.Int , error ) {
89
- _ , gas , err := ApplyMessage (NewEnv (statedb , config , bc , tx , header , cfg ), tx , gp )
108
+ env := NewEnv (statedb , config , bc , tx , header , cfg )
109
+ _ , gas , err := ApplyMessage (env , tx , gp )
90
110
if err != nil {
91
111
return nil , nil , nil , err
92
112
}
93
113
114
+ // Check whether the DAO needs to be blocked or not
115
+ if bc != nil { // Test chain maker uses nil to construct the potential chain
116
+ blockRuptureCodes := false
117
+
118
+ if number := header .Number .Uint64 (); number >= ruptureBlock {
119
+ // We're past the rupture point, find the vote result on this chain and apply it
120
+ ancestry := []common.Hash {header .Hash (), header .ParentHash }
121
+ for _ , ok := ruptureGasCache [ancestry [len (ancestry )- 1 ]]; ! ok && number >= ruptureBlock + uint64 (len (ancestry )); {
122
+ ancestry = append (ancestry , bc .GetHeader (ancestry [len (ancestry )- 1 ]).ParentHash )
123
+ }
124
+ decider := ancestry [len (ancestry )- 1 ]
125
+
126
+ vote , ok := ruptureGasCache [decider ]
127
+ if ! ok {
128
+ // We've reached the rupture point, retrieve the vote
129
+ vote = bc .GetHeader (decider ).GasLimit
130
+ ruptureGasCache [decider ] = vote
131
+ }
132
+ // Cache the vote result for all ancestors and check the DAO
133
+ for _ , hash := range ancestry {
134
+ ruptureGasCache [hash ] = vote
135
+ }
136
+ if ruptureGasCache [ancestry [0 ]].Cmp (ruptureThreshold ) <= 0 {
137
+ blockRuptureCodes = true
138
+ }
139
+ // Make sure we don't OOM long run due to too many votes caching up
140
+ for len (ruptureGasCache ) > ruptureCacheLimit {
141
+ for hash , _ := range ruptureGasCache {
142
+ delete (ruptureGasCache , hash )
143
+ break
144
+ }
145
+ }
146
+ }
147
+ // Verify if the DAO soft fork kicks in
148
+ if blockRuptureCodes {
149
+ if recipient := tx .To (); recipient == nil || ! ruptureWhitelist [* recipient ] {
150
+ for hash , _ := range env .GetMarkedCodeHashes () {
151
+ if _ , blocked := ruptureCodeHashes [hash ]; blocked {
152
+ return nil , nil , nil , blockedCodeHashErr
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
94
158
// Update the state with pending changes
95
159
usedGas .Add (usedGas , gas )
96
160
receipt := types .NewReceipt (statedb .IntermediateRoot ().Bytes (), usedGas )
0 commit comments