github.com/codingfuture/orig-energi3@v0.8.4/energi/consensus/pos_test.go (about) 1 // Copyright 2019 The Energi Core Authors 2 // This file is part of the Energi Core library. 3 // 4 // The Energi Core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The Energi Core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package consensus 18 19 import ( 20 "crypto/ecdsa" 21 "crypto/rand" 22 "math/big" 23 "testing" 24 25 "github.com/ethereum/go-ethereum/common" 26 eth_consensus "github.com/ethereum/go-ethereum/consensus" 27 "github.com/ethereum/go-ethereum/core" 28 "github.com/ethereum/go-ethereum/core/types" 29 "github.com/ethereum/go-ethereum/core/vm" 30 "github.com/ethereum/go-ethereum/crypto" 31 "github.com/ethereum/go-ethereum/ethdb" 32 "github.com/ethereum/go-ethereum/log" 33 "github.com/ethereum/go-ethereum/params" 34 35 "github.com/stretchr/testify/assert" 36 37 energi_params "energi.world/core/gen3/energi/params" 38 ) 39 40 func TestPoSChain(t *testing.T) { 41 t.Parallel() 42 log.Root().SetHandler(log.StdoutHandler) 43 44 results := make(chan *eth_consensus.SealResult, 1) 45 stop := make(chan struct{}) 46 47 signers := make(map[common.Address]*ecdsa.PrivateKey, 61) 48 addresses := make([]common.Address, 0, 60) 49 alloc := make(core.GenesisAlloc, 61) 50 for i := 0; i < 60; i++ { 51 k, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader) 52 a := crypto.PubkeyToAddress(k.PublicKey) 53 54 signers[a] = k 55 addresses = append(addresses, a) 56 alloc[a] = core.GenesisAccount{ 57 Balance: minStake, 58 } 59 } 60 alloc[energi_params.Energi_MigrationContract] = core.GenesisAccount{ 61 Balance: minStake, 62 } 63 migrationSigner := addresses[59] 64 signers[energi_params.Energi_MigrationContract] = signers[migrationSigner] 65 66 testdb := ethdb.NewMemDatabase() 67 engine := New(¶ms.EnergiConfig{MigrationSigner: migrationSigner}, testdb) 68 var header *types.Header 69 70 engine.testing = true 71 engine.SetMinerCB( 72 func() []common.Address { 73 if header.Number.Uint64() == 1 { 74 return []common.Address{ 75 energi_params.Energi_MigrationContract, 76 } 77 } 78 79 return addresses 80 }, 81 func(addr common.Address, hash []byte) ([]byte, error) { 82 return crypto.Sign(hash, signers[addr]) 83 }, 84 func() int { return 1 }, 85 ) 86 87 chainConfig := *params.EnergiTestnetChainConfig 88 chainConfig.Energi = ¶ms.EnergiConfig{ 89 MigrationSigner: migrationSigner, 90 } 91 92 var ( 93 gspec = &core.Genesis{ 94 Config: &chainConfig, 95 GasLimit: 8000000, 96 Timestamp: 1000, 97 Difficulty: big.NewInt(1), 98 Coinbase: energi_params.Energi_Treasury, 99 Alloc: alloc, 100 Xfers: core.DeployEnergiGovernance(&chainConfig), 101 } 102 genesis = gspec.MustCommit(testdb) 103 104 now = engine.now() 105 ) 106 107 chain, err := core.NewBlockChain(testdb, nil, &chainConfig, engine, vm.Config{}, nil) 108 assert.Empty(t, err) 109 defer chain.Stop() 110 111 //-- 112 _, err = chain.InsertChain([]*types.Block{genesis}) 113 assert.Empty(t, err) 114 115 parent := chain.GetHeaderByHash(genesis.Hash()) 116 assert.NotEmpty(t, parent) 117 118 iterCount := 150 119 //iterMid := iterCount * 2 / 3 120 121 engine.diffFn = func(ChainReader, uint64, *types.Header, *timeTarget) *big.Int { 122 return common.Big1 123 } 124 125 for i := 1; i < iterCount; i++ { 126 number := new(big.Int).Add(parent.Number, common.Big1) 127 128 //--- 129 header = &types.Header{ 130 ParentHash: parent.Hash(), 131 Coinbase: common.Address{}, 132 GasLimit: parent.GasLimit, 133 Number: number, 134 Time: parent.Time, 135 } 136 blstate := chain.CalculateBlockState(header.ParentHash, parent.Number.Uint64()) 137 assert.NotEmpty(t, blstate) 138 139 err = engine.Prepare(chain, header) 140 assert.Empty(t, err) 141 assert.NotEmpty(t, header.Difficulty) 142 txs := types.Transactions{} 143 receipts := []*types.Receipt{} 144 if i == 1 { 145 tx := migrationTx( 146 types.NewEIP155Signer(chainConfig.ChainID), header, 147 &snapshot{ 148 Txouts: []snapshotItem{ 149 { 150 Owner: "t6vtJKxdjaJdofaUrx7w4xUs5bMcjDq5R2", 151 Amount: big.NewInt(10228000000), 152 Atype: "pubkeyhash", 153 }, 154 }, 155 }, engine) 156 receipt, _, err := core.ApplyTransaction( 157 &chainConfig, chain, &header.Coinbase, 158 new(core.GasPool).AddGas(header.GasLimit), 159 blstate, header, tx, 160 &header.GasUsed, *chain.GetVMConfig()) 161 assert.Empty(t, err) 162 txs = append(txs, tx) 163 receipts = append(receipts, receipt) 164 } 165 block, receipts, err := engine.Finalize( 166 chain, header, blstate, txs, nil, receipts) 167 assert.Empty(t, err) 168 169 if i == 1 { 170 assert.Equal(t, 1, len(receipts)) 171 } else { 172 assert.Empty(t, receipts) 173 } 174 175 //--- 176 err = engine.Seal(chain, block, results, stop) 177 assert.Empty(t, err) 178 179 seal_res := <-results 180 block = seal_res.Block 181 blstate = seal_res.NewState 182 receipts = seal_res.Receipts 183 assert.NotEmpty(t, block) 184 assert.NotEmpty(t, blstate) 185 assert.NotEmpty(t, receipts) 186 header = block.Header() 187 //assert.NotEqual(t, parent.Coinbase, header.Coinbase, "Header %v", i) 188 assert.NotEqual(t, parent.Coinbase, common.Address{}, "Header %v", i) 189 err = engine.VerifySeal(chain, header) 190 assert.Empty(t, err) 191 192 // Test consensus tx check during block processing 193 //--- 194 if i == 2 { 195 tmptxs := block.Transactions() 196 tmpheader := *header 197 198 assert.Equal(t, len(tmptxs), 1) 199 200 _, _, err = engine.Finalize( 201 chain, &tmpheader, blstate.Copy(), tmptxs, nil, receipts) 202 assert.Empty(t, err) 203 204 _, _, err = engine.Finalize( 205 chain, &tmpheader, blstate.Copy(), append(tmptxs, tmptxs[len(tmptxs)-1]), nil, receipts) 206 assert.Equal(t, eth_consensus.ErrInvalidConsensusTx, err) 207 208 _, _, err = engine.Finalize( 209 chain, &tmpheader, blstate.Copy(), 210 append(tmptxs[:len(tmptxs)-1], tmptxs[len(tmptxs)-1].WithConsensusSender(common.Address{})), 211 nil, receipts) 212 assert.Equal(t, eth_consensus.ErrInvalidConsensusTx, err) 213 } 214 215 // Time tests 216 //--- 217 tt := engine.calcTimeTarget(chain, parent) 218 assert.True(t, tt.max_time >= now) 219 assert.True(t, tt.max_time <= engine.now()+30) 220 221 if i < 60 { 222 assert.Equal(t, header.Time, parent.Time+30) 223 224 assert.Equal(t, tt.min_time, header.Time) 225 assert.Equal(t, tt.block_target, header.Time+30) 226 } else if i < 61 { 227 assert.Equal(t, header.Time, genesis.Time()+3570) 228 assert.Equal(t, header.Time, parent.Time+1800) 229 230 assert.Equal(t, tt.min_time, header.Time) 231 assert.Equal(t, tt.block_target, parent.Time+60) 232 } else if i < 62 { 233 assert.Equal(t, header.Time, genesis.Time()+3600) 234 } 235 236 assert.True(t, parent.Time < tt.min_time, "Header %v", i) 237 238 _, err = chain.WriteBlockWithState(block, receipts, blstate) 239 assert.Empty(t, err) 240 241 // Stake amount tests 242 //--- 243 // TODO: 244 245 //--- 246 247 parent = header 248 } 249 } 250 251 func TestPoSDiffV1(t *testing.T) { 252 t.Parallel() 253 log.Root().SetHandler(log.StdoutHandler) 254 255 type TC struct { 256 parent int64 257 time uint64 258 min uint64 259 btarget uint64 260 ptarget uint64 261 result uint64 262 } 263 264 tests := []TC{ 265 { 266 parent: 100, 267 time: 61, 268 min: 31, 269 btarget: 61, 270 ptarget: 61, 271 result: 100, 272 }, 273 { 274 parent: 100, 275 time: 31, 276 min: 31, 277 btarget: 61, 278 ptarget: 61, 279 result: 1744, 280 }, 281 { 282 parent: 100, 283 time: 31, 284 min: 31, 285 btarget: 51, 286 ptarget: 71, 287 result: 1744, 288 }, 289 { 290 parent: 100, 291 time: 31, 292 min: 61, 293 btarget: 31, 294 ptarget: 31, 295 result: 1744, 296 }, 297 { 298 parent: 100, 299 time: 31, 300 min: 31, 301 btarget: 31, 302 ptarget: 31, 303 result: 100, 304 }, 305 { 306 parent: 1744, 307 time: 91, 308 min: 31, 309 btarget: 61, 310 ptarget: 61, 311 result: 403, 312 }, 313 { 314 parent: 1744, 315 time: 121, 316 min: 31, 317 btarget: 61, 318 ptarget: 61, 319 result: 93, 320 }, 321 { 322 parent: 1744, 323 time: 200, 324 min: 31, 325 btarget: 61, 326 ptarget: 61, 327 result: 4, 328 }, 329 { 330 parent: 1744, 331 time: 181, 332 min: 31, 333 btarget: 61, 334 ptarget: 61, 335 result: 4, 336 }, 337 } 338 339 for i, tc := range tests { 340 parent := &types.Header{ 341 Difficulty: big.NewInt(tc.parent), 342 } 343 tt := &timeTarget{ 344 min_time: tc.min, 345 block_target: tc.btarget, 346 period_target: tc.ptarget, 347 } 348 349 res := calcPoSDifficultyV1(nil, tc.time, parent, tt) 350 assert.Equal(t, tc.result, res.Uint64(), "TC %v", i) 351 } 352 }