@@ -22,6 +22,7 @@ import (
22
22
23
23
"github.com/iotexproject/go-pkgs/hash"
24
24
"github.com/iotexproject/iotex-address/address"
25
+ "github.com/iotexproject/iotex-proto/golang/iotextypes"
25
26
26
27
"github.com/iotexproject/iotex-core/action"
27
28
"github.com/iotexproject/iotex-core/action/protocol"
@@ -44,37 +45,39 @@ import (
44
45
"github.com/iotexproject/iotex-core/db/trie"
45
46
"github.com/iotexproject/iotex-core/db/trie/mptrie"
46
47
"github.com/iotexproject/iotex-core/pkg/unit"
48
+ "github.com/iotexproject/iotex-core/state"
47
49
"github.com/iotexproject/iotex-core/state/factory"
48
50
"github.com/iotexproject/iotex-core/test/identityset"
49
51
"github.com/iotexproject/iotex-core/test/mock/mock_blockcreationsubscriber"
50
52
"github.com/iotexproject/iotex-core/testutil"
51
53
)
52
54
53
55
var (
54
- deployHash hash.Hash256 // in block 2
55
- setHash hash.Hash256 // in block 3
56
- shrHash hash.Hash256 // in block 4
57
- shlHash hash.Hash256 // in block 5
58
- sarHash hash.Hash256 // in block 6
59
- extHash hash.Hash256 // in block 7
60
- crt2Hash hash.Hash256 // in block 8
61
- setTopic , _ = hex .DecodeString ("fe00000000000000000000000000000000000000000000000000000000001f40" ) // in block 3
62
- getTopic , _ = hex .DecodeString ("0000000000000000000000000000000000000000000000000000000000000001" ) // in block 4
63
- shrTopic , _ = hex .DecodeString ("00fe00000000000000000000000000000000000000000000000000000000001f" ) // in block 4
64
- shlTopic , _ = hex .DecodeString ("fe00000000000000000000000000000000000000000000000000000000001f00" ) // in block 5
65
- sarTopic , _ = hex .DecodeString ("fffe00000000000000000000000000000000000000000000000000000000001f" ) // in block 6
66
- extTopic , _ = hex .DecodeString ("4a98ce81a2fd5177f0f42b49cb25b01b720f9ce8019f3937f63b789766c938e2" ) // in block 7
67
- crt2Topic , _ = hex .DecodeString ("0000000000000000000000001895e6033cd1081f18e0bd23a4501d9376028523" ) // in block 8
56
+ deployHash hash.Hash256 // in block 1
57
+ setHash hash.Hash256 // in block 2
58
+ shrHash hash.Hash256 // in block 3
59
+ shlHash hash.Hash256 // in block 4
60
+ sarHash hash.Hash256 // in block 5
61
+ extHash hash.Hash256 // in block 6
62
+ crt2Hash hash.Hash256 // in block 7
63
+ storeHash hash.Hash256 // in block 8
64
+ store2Hash hash.Hash256 // in block 9
65
+ setTopic , _ = hex .DecodeString ("fe00000000000000000000000000000000000000000000000000000000001f40" ) // in block 2
66
+ getTopic , _ = hex .DecodeString ("0000000000000000000000000000000000000000000000000000000000000001" ) // in block 2
67
+ shrTopic , _ = hex .DecodeString ("00fe00000000000000000000000000000000000000000000000000000000001f" ) // in block 3
68
+ shlTopic , _ = hex .DecodeString ("fe00000000000000000000000000000000000000000000000000000000001f00" ) // in block 4
69
+ sarTopic , _ = hex .DecodeString ("fffe00000000000000000000000000000000000000000000000000000000001f" ) // in block 5
70
+ extTopic , _ = hex .DecodeString ("4a98ce81a2fd5177f0f42b49cb25b01b720f9ce8019f3937f63b789766c938e2" ) // in block 6
71
+ crt2Topic , _ = hex .DecodeString ("0000000000000000000000001895e6033cd1081f18e0bd23a4501d9376028523" ) // in block 7
72
+ preGrPreStore * big.Int
73
+ preGrPostStore * big.Int
74
+ postGrPostStore * big.Int
68
75
)
69
76
70
- func addTestingConstantinopleBlocks (bc blockchain.Blockchain , dao blockdao.BlockDAO , ap actpool.ActPool ) error {
77
+ func addTestingConstantinopleBlocks (bc blockchain.Blockchain , dao blockdao.BlockDAO , sf factory. Factory , ap actpool.ActPool ) error {
71
78
// Add block 1
72
79
priKey0 := identityset .PrivateKey (27 )
73
- data , err := hex .DecodeString ("608060405234801561001057600080fd5b506104d5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806381ea44081161005b57806381ea440814610101578063a91b336214610159578063c2bc2efc14610177578063f5eacece146101cf57610088565b80635bec9e671461008d57806360fe47b1146100975780636bc8ecaa146100c5578063744f5f83146100e3575b600080fd5b6100956101ed565b005b6100c3600480360360208110156100ad57600080fd5b8101908080359060200190929190505050610239565b005b6100cd610270565b6040518082815260200191505060405180910390f35b6100eb6102b3565b6040518082815260200191505060405180910390f35b6101436004803603602081101561011757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102f6565b6040518082815260200191505060405180910390f35b61016161036a565b6040518082815260200191505060405180910390f35b6101b96004803603602081101561018d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506103ad565b6040518082815260200191505060405180910390f35b6101d761045f565b6040518082815260200191505060405180910390f35b5b60011561020b5760008081548092919060010191905055506101ee565b7f8bfaa460932ccf8751604dd60efa3eafa220ec358fccb32ef703f91c509bc3ea60405160405180910390a1565b80600081905550807fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b60405160405180910390a250565b6000805460081d905080600081905550807fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b60405160405180910390a280905090565b6000805460081c905080600081905550807fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b60405160405180910390a280905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561033157600080fd5b813f9050807fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b60405160405180910390a2809050919050565b6000805460081b905080600081905550807fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b60405160405180910390a280905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156103e857600080fd5b7fbde7a70c2261170a87678200113c8e12f82f63d0a1d1cfa45681cbac328e87e382600054604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a16000549050919050565b60008080602060406000f59150817fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b60405160405180910390a2819150509056fea265627a7a72305820209a8ef04c4d621759f34878b27b238650e8605c8a71d6efc619a769a64aa9cc64736f6c634300050a0032" )
74
- if err != nil {
75
- return err
76
- }
77
- ex1 , err := testutil .SignedExecution (action .EmptyAddress , priKey0 , 1 , big .NewInt (0 ), 500000 , big .NewInt (testutil .TestGasPriceInt64 ), data )
80
+ ex1 , err := testutil .SignedExecution (action .EmptyAddress , priKey0 , 1 , big .NewInt (0 ), 500000 , big .NewInt (testutil .TestGasPriceInt64 ), _constantinopleOpCodeContract )
78
81
if err != nil {
79
82
return err
80
83
}
@@ -101,8 +104,8 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block
101
104
contract = r .ContractAddress
102
105
}
103
106
104
- addOneBlock := func (nonce uint64 , data []byte ) (hash.Hash256 , error ) {
105
- ex1 , err := testutil .SignedExecution (contract , priKey0 , nonce , big . NewInt ( 0 ), testutil . TestGasLimit * 5 , big . NewInt ( testutil . TestGasPriceInt64 ) , data )
107
+ addOneBlock := func (contract string , nonce uint64 , amount * big. Int , gasLimit uint64 , gasPrice * big. Int , data []byte ) (hash.Hash256 , error ) {
108
+ ex1 , err := testutil .SignedExecution (contract , priKey0 , nonce , amount , gasLimit , gasPrice , data )
106
109
if err != nil {
107
110
return hash .ZeroHash256 , err
108
111
}
@@ -120,35 +123,41 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block
120
123
return ex1 .Hash (), nil
121
124
}
122
125
126
+ var (
127
+ zero = big .NewInt (0 )
128
+ gasLimit = testutil .TestGasLimit * 5
129
+ gasPrice = big .NewInt (testutil .TestGasPriceInt64 )
130
+ )
131
+
123
132
// Add block 2
124
133
// call set() to set storedData = 0xfe...1f40
125
134
funcSig := hash .Hash256b ([]byte ("set(uint256)" ))
126
- data = append (funcSig [:4 ], setTopic ... )
127
- setHash , err = addOneBlock (2 , data )
135
+ data : = append (funcSig [:4 ], setTopic ... )
136
+ setHash , err = addOneBlock (contract , 2 , zero , gasLimit , gasPrice , data )
128
137
if err != nil {
129
138
return err
130
139
}
131
140
132
141
// Add block 3
133
142
// call shright() to test SHR opcode, storedData => 0x00fe...1f
134
143
funcSig = hash .Hash256b ([]byte ("shright()" ))
135
- shrHash , err = addOneBlock (3 , funcSig [:4 ])
144
+ shrHash , err = addOneBlock (contract , 3 , zero , gasLimit , gasPrice , funcSig [:4 ])
136
145
if err != nil {
137
146
return err
138
147
}
139
148
140
149
// Add block 4
141
150
// call shleft() to test SHL opcode, storedData => 0xfe...1f00
142
151
funcSig = hash .Hash256b ([]byte ("shleft()" ))
143
- shlHash , err = addOneBlock (4 , funcSig [:4 ])
152
+ shlHash , err = addOneBlock (contract , 4 , zero , gasLimit , gasPrice , funcSig [:4 ])
144
153
if err != nil {
145
154
return err
146
155
}
147
156
148
157
// Add block 5
149
158
// call saright() to test SAR opcode, storedData => 0xfffe...1f
150
159
funcSig = hash .Hash256b ([]byte ("saright()" ))
151
- sarHash , err = addOneBlock (5 , funcSig [:4 ])
160
+ sarHash , err = addOneBlock (contract , 5 , zero , gasLimit , gasPrice , funcSig [:4 ])
152
161
if err != nil {
153
162
return err
154
163
}
@@ -159,18 +168,72 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block
159
168
addr , _ := address .FromString (contract )
160
169
ethaddr := hash .BytesToHash256 (addr .Bytes ())
161
170
data = append (funcSig [:4 ], ethaddr [:]... )
162
- extHash , err = addOneBlock (6 , data )
171
+ extHash , err = addOneBlock (contract , 6 , zero , gasLimit , gasPrice , data )
163
172
if err != nil {
164
173
return err
165
174
}
166
175
167
176
// Add block 7
168
177
// call create2() to test CREATE2 opcode
169
178
funcSig = hash .Hash256b ([]byte ("create2()" ))
170
- crt2Hash , err = addOneBlock (7 , funcSig [:4 ])
179
+ crt2Hash , err = addOneBlock (contract , 7 , zero , gasLimit , gasPrice , funcSig [:4 ])
180
+ if err != nil {
181
+ return err
182
+ }
183
+
184
+ // Add block 8
185
+ // test store out of gas
186
+ var (
187
+ caller state.Account
188
+ callerAddr = hash .BytesToHash160 (identityset .Address (27 ).Bytes ())
189
+ )
190
+ _ , err = sf .State (& caller , protocol .LegacyKeyOption (callerAddr ))
191
+ if err != nil {
192
+ return err
193
+ }
194
+ preGrPreStore = new (big.Int ).Set (caller .Balance )
195
+ storeHash , err = addOneBlock (action .EmptyAddress , 8 , unit .ConvertIotxToRau (10000 ), 3000000 , big .NewInt (unit .Qev ), _codeStoreOutOfGasContract )
196
+ if err != nil {
197
+ return err
198
+ }
199
+
200
+ if dao != nil {
201
+ r , err := dao .GetReceiptByActionHash (storeHash , 8 )
202
+ if err != nil {
203
+ return err
204
+ }
205
+ if r .Status != uint64 (iotextypes .ReceiptStatus_ErrCodeStoreOutOfGas ) {
206
+ return blockchain .ErrBalance
207
+ }
208
+ }
209
+
210
+ // Add block 9
211
+ // test store out of gas
212
+ _ , err = sf .State (& caller , protocol .LegacyKeyOption (callerAddr ))
213
+ if err != nil {
214
+ return err
215
+ }
216
+ preGrPostStore = new (big.Int ).Set (caller .Balance )
217
+ store2Hash , err = addOneBlock (action .EmptyAddress , 9 , unit .ConvertIotxToRau (10000 ), 3000000 , big .NewInt (unit .Qev ), _codeStoreOutOfGasContract )
171
218
if err != nil {
172
219
return err
173
220
}
221
+
222
+ if dao != nil {
223
+ r , err := dao .GetReceiptByActionHash (store2Hash , 9 )
224
+ if err != nil {
225
+ return err
226
+ }
227
+ if r .Status != uint64 (iotextypes .ReceiptStatus_ErrCodeStoreOutOfGas ) {
228
+ return blockchain .ErrBalance
229
+ }
230
+ }
231
+
232
+ _ , err = sf .State (& caller , protocol .LegacyKeyOption (callerAddr ))
233
+ if err != nil {
234
+ return err
235
+ }
236
+ postGrPostStore = new (big.Int ).Set (caller .Balance )
174
237
return nil
175
238
}
176
239
@@ -698,9 +761,12 @@ func TestConstantinople(t *testing.T) {
698
761
require .NoError (bc .Stop (ctx ))
699
762
}()
700
763
701
- require .NoError (addTestingConstantinopleBlocks (bc , dao , ap ))
764
+ require .NoError (addTestingConstantinopleBlocks (bc , dao , sf , ap ))
702
765
703
- // TODO: don't use hard coded hash
766
+ // reason to use hard-coded hash value here:
767
+ // this test TestConstantinople() is added when we upgrade our EVM to enable Constantinople
768
+ // at that time, the test is run with both EVM version (Byzantium vs. Constantinople), and it generates the
769
+ // same exact block hash, so these values stood as gatekeeper for backward-compatibility
704
770
hashTopic := []struct {
705
771
h hash.Hash256
706
772
blkHash string
@@ -776,17 +842,79 @@ func TestConstantinople(t *testing.T) {
776
842
}
777
843
}
778
844
845
+ storeOutGasTests := []struct {
846
+ height uint64
847
+ actHash hash.Hash256
848
+ status iotextypes.ReceiptStatus
849
+ preBalance * big.Int
850
+ postBalance * big.Int
851
+ }{
852
+ {
853
+ 8 , storeHash , iotextypes .ReceiptStatus_ErrCodeStoreOutOfGas , preGrPreStore , preGrPostStore ,
854
+ },
855
+ {
856
+ 9 , store2Hash , iotextypes .ReceiptStatus_ErrCodeStoreOutOfGas , preGrPostStore , postGrPostStore ,
857
+ },
858
+ }
859
+ caller := identityset .Address (27 )
860
+ for _ , v := range storeOutGasTests {
861
+ r , err := dao .GetReceiptByActionHash (v .actHash , v .height )
862
+ require .NoError (err )
863
+ require .EqualValues (v .status , r .Status )
864
+
865
+ // verify transaction log
866
+ bLog , err := dao .TransactionLogs (v .height )
867
+ require .NoError (err )
868
+ tLog := bLog .Logs [0 ]
869
+ // first transaction log is gas fee
870
+ tx := tLog .Transactions [0 ]
871
+ require .Equal (tx .Sender , caller .String ())
872
+ require .Equal (tx .Recipient , address .RewardingPoolAddr )
873
+ require .Equal (iotextypes .TransactionLogType_GAS_FEE , tx .Type )
874
+ gasFee , ok := new (big.Int ).SetString (tx .Amount , 10 )
875
+ require .True (ok )
876
+ postBalance := new (big.Int ).Sub (v .preBalance , gasFee )
877
+
878
+ hu := config .NewHeightUpgrade (& cfg .Genesis )
879
+ if hu .IsPre (config .Greenland , v .height ) {
880
+ // pre-Greenland contains a tx with status = ReceiptStatus_ErrCodeStoreOutOfGas
881
+ // due to a bug the transfer is not reverted
882
+ require .Equal (3 , len (tLog .Transactions ))
883
+ // 2nd log is in-contract-transfer
884
+ tx = tLog .Transactions [1 ]
885
+ require .Equal (tx .Sender , caller .String ())
886
+ require .Equal (iotextypes .TransactionLogType_IN_CONTRACT_TRANSFER , tx .Type )
887
+ tsfAmount , ok := new (big.Int ).SetString (tx .Amount , 10 )
888
+ require .True (ok )
889
+ postBalance .Sub (postBalance , tsfAmount )
890
+ // post = pre - gasFee - in_contract_transfer
891
+ require .Equal (v .postBalance , postBalance )
892
+ // 3rd log is also in-contract-transfer
893
+ tx = tLog .Transactions [2 ]
894
+ require .Equal (tx .Recipient , caller .String ())
895
+ require .Equal (iotextypes .TransactionLogType_IN_CONTRACT_TRANSFER , tx .Type )
896
+ } else {
897
+ // post-Greenland fixed that bug, the transfer is reverted so it only contains the gas fee
898
+ require .Equal (1 , len (tLog .Transactions ))
899
+ // post = pre - gasFee (transfer is reverted)
900
+ require .Equal (v .postBalance , postBalance )
901
+ }
902
+ }
903
+
779
904
// test getActions
780
- addr27 := hash .BytesToHash160 (identityset . Address ( 27 ) .Bytes ())
905
+ addr27 := hash .BytesToHash160 (caller .Bytes ())
781
906
total , err := indexer .GetActionCountByAddress (addr27 )
782
907
require .NoError (err )
783
- require .EqualValues (7 , total )
908
+ require .EqualValues (len ( hashTopic ) + len ( storeOutGasTests ) , total )
784
909
actions , err := indexer .GetActionsByAddress (addr27 , 0 , total )
785
910
require .NoError (err )
786
911
require .EqualValues (total , len (actions ))
787
- for i := range actions {
912
+ for i := range hashTopic {
788
913
require .Equal (hashTopic [i ].h [:], actions [i ])
789
914
}
915
+ for i := range storeOutGasTests {
916
+ require .Equal (storeOutGasTests [i ].actHash [:], actions [i + len (hashTopic )])
917
+ }
790
918
}
791
919
792
920
cfg := config .Default
@@ -814,6 +942,8 @@ func TestConstantinople(t *testing.T) {
814
942
cfg .Chain .EnableAsyncIndexWrite = false
815
943
cfg .ActPool .MinGasPriceStr = "0"
816
944
cfg .Genesis .AleutianBlockHeight = 2
945
+ cfg .Genesis .BeringBlockHeight = 8
946
+ cfg .Genesis .GreenlandBlockHeight = 9
817
947
cfg .Genesis .InitBalanceMap [identityset .Address (27 ).String ()] = unit .ConvertIotxToRau (10000000000 ).String ()
818
948
819
949
t .Run ("test Constantinople contract" , func (t * testing.T ) {
0 commit comments