github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/consensus/vdpos/tx.go (about) 1 // Copyright 2019 The inb-go Authors 2 // This file is part of the inb-go library. 3 // 4 // The inb-go 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 MiningReward, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The inb-go 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 inb-go library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package vdpos implements the delegated-proof-of-stake consensus engine. 18 package vdpos 19 20 import ( 21 "encoding/json" 22 "github.com/insight-chain/inb-go/log" 23 "github.com/insight-chain/inb-go/params" 24 "github.com/pkg/errors" 25 "math/big" 26 "strings" 27 28 "github.com/insight-chain/inb-go/common" 29 "github.com/insight-chain/inb-go/consensus" 30 "github.com/insight-chain/inb-go/core/state" 31 "github.com/insight-chain/inb-go/core/types" 32 "github.com/insight-chain/inb-go/rlp" 33 ) 34 35 // HeaderExtra is the struct of info in header.Extra[extraVanity:len(header.extra)-extraSeal] 36 // HeaderExtra is the current struct 37 type HeaderExtra struct { 38 LoopStartTime uint64 39 SignersPool []common.Address 40 SignerMissing []common.Address 41 ConfirmedBlockNumber uint64 42 //Enodes []common.SuperNode 43 } 44 45 func encodeHeaderExtra(val HeaderExtra) ([]byte, error) { 46 var headerExtra interface{} 47 headerExtra = val 48 return rlp.EncodeToBytes(headerExtra) 49 50 } 51 52 func decodeHeaderExtra(b []byte, val *HeaderExtra) error { 53 var err error 54 err = rlp.DecodeBytes(b, val) 55 return err 56 } 57 58 // Calculate Votes from transaction in this block, write into header.Extra 59 func (v *Vdpos) processCustomTx(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, vdposContext *types.VdposContext) error { 60 61 for _, tx := range txs { 62 txSender, err := types.Sender(types.NewEIP155Signer(tx.ChainId()), tx) 63 if err != nil { 64 log.Error("Fail to get txSender", "err", err) 65 continue 66 } 67 68 txData := string(tx.Data()) 69 //2019.8.5 inb mod by ghy begin 70 if tx.WhichTypes(types.Vote) { 71 var candidates []common.Address 72 candidatesStr := strings.Split(txData, ",") 73 for _, value := range candidatesStr { 74 address := common.HexToAddress(value) 75 candidates = append(candidates, address) 76 } 77 if params.TxConfig.CandidateSize < uint64(len(candidates)) { 78 log.Error("Candidates over size") 79 continue 80 } 81 err = v.processEventVote(state, txSender, candidates, vdposContext) 82 if err != nil { 83 log.Error("Fail in Vdpos.processEventVote()", "err", err) 84 continue 85 } 86 87 } 88 89 if tx.WhichTypes(types.UpdateNodeInformation) { 90 if state.GetStakingValue(txSender).Cmp(BeVotedNeedINB) == 1 { 91 err = v.processEventDeclare(tx.Data(), txSender, vdposContext) 92 if err != nil { 93 log.Error("Fail in Vdpos.processEventDeclare()", "err", err) 94 continue 95 } 96 } else { 97 log.Error("Update node info account mortgage less than %v inb", BeVotedNeedINB) 98 continue 99 } 100 } 101 102 if tx.WhichTypes(types.IssueLightToken) { 103 err = v.processEventIssueLightToken(tx, txSender, vdposContext) 104 if err != nil { 105 log.Error("Fail in Vdpos.processEventIssueLightToken()", "err", err) 106 continue 107 } 108 } 109 110 if tx.WhichTypes(types.TransferLightToken) { 111 txReceiver := *tx.To() 112 value := tx.Value() 113 err = v.processEventTransferLightToken(txData, txSender, txReceiver, value, vdposContext) 114 if err != nil { 115 log.Error("Fail in Vdpos.processEventTransferLightToken()", "err", err) 116 continue 117 } 118 } 119 120 if tx.WhichTypes(types.RegularLightToken) { 121 err = v.processEventRegularLightToken(tx, txSender, header.Number, vdposContext) 122 if err != nil { 123 log.Error("Fail in Vdpos.processEventRegularLightToken()", "err", err) 124 continue 125 } 126 } 127 128 if tx.WhichTypes(types.RedeemLightToken) { 129 err = v.processEventRedeemLightToken(tx, txSender, header.Number, vdposContext) 130 if err != nil { 131 log.Error("Fail in Vdpos.processEventRedeemLightToken()", "err", err) 132 continue 133 } 134 } 135 136 if tx.WhichTypes(types.InsteadRegularLightToken) { 137 err = v.processEventInsteadRegularLightToken(tx, txSender, header.Number, vdposContext) 138 if err != nil { 139 log.Error("Fail in Vdpos.processEventInsteadRegularLightToken()", "err", err) 140 continue 141 } 142 } 143 144 // check each address 145 number := header.Number.Uint64() 146 if number > 1 { 147 err = v.processPredecessorVoter(state, tx, txSender, vdposContext) 148 if err != nil { 149 log.Error("Fail in Vdpos.processPredecessorVoter()", "err", err) 150 continue 151 } 152 } 153 154 } 155 156 //2019.8.5 inb mod by ghy end 157 158 return nil 159 } 160 161 func (v *Vdpos) processEventVote(state *state.StateDB, voter common.Address, candidates []common.Address, vdposContext *types.VdposContext) error { 162 v.lock.RLock() 163 stakingValue := state.GetStakingValue(voter) 164 v.lock.RUnlock() 165 166 vote := &types.Votes{ 167 Voter: voter, 168 Candidate: candidates, 169 StakingValue: stakingValue, 170 } 171 172 err := vdposContext.UpdateTallysByVotes(vote, state) 173 if err != nil { 174 return err 175 } 176 err = vdposContext.UpdateVotes(vote) 177 if err != nil { 178 return err 179 } 180 181 return nil 182 } 183 184 func (v *Vdpos) processEventDeclare(txDataInfo []byte, declarer common.Address, vdposContext *types.VdposContext) error { 185 186 //inb by ghy begin 187 nodeInfo := new(common.SuperNodeExtra) 188 if err := json.Unmarshal(txDataInfo, nodeInfo); err != nil { 189 return err 190 } 191 enodeInfo := common.SuperNode{ 192 Id: nodeInfo.Id, 193 Ip: nodeInfo.Ip, 194 Port: nodeInfo.Port, 195 Address: declarer, 196 RewardAccount: nodeInfo.RewardAccount, 197 } 198 199 nodeInfo.Address = declarer 200 201 //enodeInfo.Id = midEnodeInfo[PosEventDeclareInfoId] 202 //enodeInfo.Ip = midEnodeInfo[PosEventDeclareInfoIp] 203 //enodeInfo.Port = midEnodeInfo[PosEventDeclareInfoPort] 204 //enodeInfo.Address = declarer 205 206 //data := `{` 207 //if len(midEnodeInfo) >= 10 { 208 // enodeData := strings.Split(midEnodeInfo[PosEventDeclareInfoData], "-") 209 // for _, v := range enodeData { 210 // split := strings.Split(v, "/") 211 // if len(split) == 2 { 212 // data += `"` + split[0] + `":"` + split[1] + `",` 213 // } 214 // } 215 // data = strings.TrimRight(data, ",") 216 //} 217 //data += `}` 218 //enodeInfoTrie.ExtraData = data 219 220 //2019.9.4 mod by ghy 221 err := vdposContext.UpdateTallysByNodeInfo(*nodeInfo) 222 if err != nil { 223 return err 224 } 225 //inb by ghy end 226 227 currentEnodeInfos, err := vdposContext.GetSuperNodesFromTrie() 228 if err != nil { 229 return err 230 } 231 flag := false 232 for i, enode := range currentEnodeInfos { 233 if enode.Address == declarer { 234 flag = true 235 currentEnodeInfos[i] = enodeInfo 236 break 237 } 238 } 239 if !flag { 240 currentEnodeInfos = append(currentEnodeInfos, enodeInfo) 241 } 242 err = vdposContext.SetSuperNodesToTrie(currentEnodeInfos) 243 if err != nil { 244 return err 245 } 246 247 return nil 248 } 249 250 //inb by ghy end 251 252 // inb by ssh 190904 begin 253 func (v *Vdpos) processPredecessorVoter(state *state.StateDB, tx *types.Transaction, txSender common.Address, vdposContext *types.VdposContext) error { 254 // process 5 kinds of transactions which relate to voter 255 if tx.Value().Cmp(big.NewInt(0)) > 0 { 256 if tx.WhichTypes(types.Mortgage) || tx.WhichTypes(types.Regular) || tx.WhichTypes(types.Redeem) { 257 v.lock.RLock() 258 stake := state.GetStakingValue(txSender) 259 v.lock.RUnlock() 260 err := vdposContext.UpdateTallysByNewState(txSender, state) 261 if err != nil { 262 return err 263 } 264 err = vdposContext.UpdateTallysAndVotesByMPV(txSender, stake) 265 if err != nil { 266 return err 267 } 268 } 269 } 270 if tx.WhichTypes(types.ReceiveLockedAward) { 271 v.lock.RLock() 272 stake := state.GetStakingValue(txSender) 273 v.lock.RUnlock() 274 err := vdposContext.UpdateTallysByNewState(txSender, state) 275 if err != nil { 276 return err 277 } 278 err = vdposContext.UpdateTallysAndVotesByMPV(txSender, stake) 279 if err != nil { 280 return err 281 } 282 } 283 if tx.WhichTypes(types.InsteadMortgage) { 284 txReceiver := *tx.To() 285 v.lock.RLock() 286 stake := state.GetStakingValue(txReceiver) 287 v.lock.RUnlock() 288 err := vdposContext.UpdateTallysByNewState(txReceiver, state) 289 if err != nil { 290 return err 291 } 292 err = vdposContext.UpdateTallysAndVotesByMPV(txReceiver, stake) 293 if err != nil { 294 return err 295 } 296 } 297 298 return nil 299 } 300 301 // inb by ssh 190904 end 302 303 func (v *Vdpos) processEventIssueLightToken(tx *types.Transaction, txSender common.Address, vdposContext *types.VdposContext) error { 304 lightTokenJson := new(types.LightTokenJson) 305 if err := json.Unmarshal(tx.Data(), lightTokenJson); err != nil { 306 return err 307 } 308 309 //txDataInfo := string(tx.Data()) 310 //lightTokenInfo := strings.Split(txDataInfo, "~") 311 //if len(lightTokenInfo) < PosEventIssueLightTokenSplitLen { 312 // return errors.Errorf("issue lightToken need 4 parameter") 313 //} else { 314 // name := lightTokenInfo[PosEventIssueLightTokenName] 315 // symbol := lightTokenInfo[PosEventIssueLightTokenSymbol] 316 // decimalsStr := lightTokenInfo[PosEventIssueLightTokenDecimals] 317 // decimalsNum, err := strconv.ParseUint(decimalsStr, 10, 64) 318 // if err != nil { 319 // return errors.Errorf("decimals is not uint8") 320 // } else if decimalsNum > 5 { 321 // return errors.Errorf("decimals must from 0~5") 322 // } 323 // decimals := uint8(decimalsNum) 324 // totalSupplyStr := lightTokenInfo[PosEventIssueLightTokenTotalSupply] 325 // totalSupply, ok := new(big.Int).SetString(totalSupplyStr, 10) 326 // if !ok { 327 // return errors.Errorf("unable to convert string to big integer: %v", totalSupplyStr) 328 // } 329 txHash := tx.Hash() 330 lightTokenAddressBytes := append([]byte{149}, txHash[:19]...) 331 lightTokenAddress := common.BytesToAddress(lightTokenAddressBytes) 332 333 // first update lightTokenTrie 334 lightToken := &types.LightToken{ 335 Address: lightTokenAddress, 336 Name: lightTokenJson.Name, 337 Symbol: lightTokenJson.Symbol, 338 Decimals: lightTokenJson.Decimals, 339 TotalSupply: lightTokenJson.TotalSupply, 340 IssuedAccountAddress: txSender, 341 IssuedTxHash: txHash, 342 Owner: txSender, 343 PayForInb: tx.Value(), 344 Type: 1, 345 TotalStakings: big.NewInt(0), 346 } 347 //lightTokenExist, err := vdposContext.GetLightToken(lightTokenAddress) 348 //if lightTokenExist != nil { 349 // if err != nil { 350 // return errors.Errorf("err in vdposContext.GetLightToken()") 351 // } else { 352 // return errors.Errorf("this lightToken has already exist") 353 // } 354 //} 355 err := vdposContext.UpdateLightToken(lightToken) 356 if err != nil { 357 return err 358 } 359 360 // second update lightTokenAccountTrie 361 lightTokenChanges := new(types.LightTokenChanges) 362 lightTokenChanges.LTCs = append(lightTokenChanges.LTCs, &types.LightTokenChange{ 363 AccountAddress: txSender, 364 LightTokenAddress: lightTokenAddress, 365 LT: lightToken, 366 ChangeBalance: lightTokenJson.TotalSupply, 367 ChangeType: types.Add, 368 }) 369 err = vdposContext.UpdateLightTokenAccount(lightTokenChanges) 370 if err != nil { 371 return err 372 } 373 374 return nil 375 } 376 377 func (v *Vdpos) processEventTransferLightToken(txData string, txSender common.Address, txReceiver common.Address, value *big.Int, vdposContext *types.VdposContext) error { 378 lightTokenAddress := common.HexToAddress(txData) 379 // check up if lightToken exist 380 lightTokenExist, err := vdposContext.GetLightToken(lightTokenAddress) 381 if lightTokenExist == nil { 382 return errors.Errorf("this lightToken do not exist") 383 } else { 384 if err != nil { 385 return errors.Errorf("err in vdposContext.GetLightToken()") 386 } 387 } 388 389 // check up if balance is enough 390 senderBalance, err := vdposContext.GetLightTokenBalanceByAddress(txSender, lightTokenAddress) 391 if err != nil { 392 return errors.Errorf("err in vdposContext.GetLightTokenBalanceByAddress()") 393 } else { 394 if senderBalance.Cmp(value) == -1 { 395 return errors.Errorf("not enough lightToken balance to transfer") 396 } else { 397 lightTokenChanges := new(types.LightTokenChanges) 398 lightTokenChanges.LTCs = append(lightTokenChanges.LTCs, &types.LightTokenChange{ 399 AccountAddress: txSender, 400 LightTokenAddress: lightTokenAddress, 401 LT: lightTokenExist, 402 ChangeBalance: value, 403 ChangeType: types.Sub, 404 }, &types.LightTokenChange{ 405 AccountAddress: txReceiver, 406 LightTokenAddress: lightTokenAddress, 407 LT: lightTokenExist, 408 ChangeBalance: value, 409 ChangeType: types.Add, 410 }) 411 err = vdposContext.UpdateLightTokenAccount(lightTokenChanges) 412 if err != nil { 413 return err 414 } 415 } 416 } 417 418 return nil 419 } 420 421 func (v *Vdpos) processEventRegularLightToken(tx *types.Transaction, txSender common.Address, blockNum *big.Int, vdposContext *types.VdposContext) error { 422 stakingJson := new(types.StakingJson) 423 if err := json.Unmarshal(tx.Data(), stakingJson); err != nil { 424 return err 425 } 426 427 lightTokenAddress := stakingJson.LightTokenAddress 428 lockHeights := stakingJson.LockHeights 429 stakingValue := tx.Value() 430 431 // first update lightTokenTrie 432 lightToken, err := vdposContext.UpdateLightTokenByTotalStakings(lightTokenAddress, stakingValue, types.Add) 433 if err != nil { 434 return err 435 } 436 437 // second update lightTokenAccountTrie 438 lightTokenChanges := new(types.LightTokenChanges) 439 lightTokenChanges.LTCs = append(lightTokenChanges.LTCs, &types.LightTokenChange{ 440 AccountAddress: txSender, 441 LightTokenAddress: lightTokenAddress, 442 LT: lightToken, 443 ChangeBalance: stakingValue, 444 ChangeType: types.Stake, 445 ChangeStaking: &types.Staking{ 446 Hash: tx.Hash(), 447 StartHeight: blockNum, 448 LockHeights: lockHeights, 449 Value: stakingValue, 450 }, 451 }) 452 err = vdposContext.UpdateLightTokenAccount(lightTokenChanges) 453 if err != nil { 454 return err 455 } 456 457 return nil 458 } 459 460 func (v *Vdpos) processEventRedeemLightToken(tx *types.Transaction, txSender common.Address, blockNum *big.Int, vdposContext *types.VdposContext) error { 461 unStakingJson := new(types.UnStakingJson) 462 if err := json.Unmarshal(tx.Data(), unStakingJson); err != nil { 463 return err 464 } 465 466 lightTokenAddress := unStakingJson.LightTokenAddress 467 stakingHash := unStakingJson.StakingHash 468 469 // first get the staking record 470 staking, err := vdposContext.GetStakingByHash(txSender, lightTokenAddress, stakingHash) 471 if err != nil { 472 return err 473 } 474 475 // second update lightTokenTrie 476 lightToken, err := vdposContext.UpdateLightTokenByTotalStakings(lightTokenAddress, staking.Value, types.Sub) 477 if err != nil { 478 return err 479 } 480 481 // third update lightTokenAccountTrie 482 lightTokenChanges := new(types.LightTokenChanges) 483 lightTokenChanges.LTCs = append(lightTokenChanges.LTCs, &types.LightTokenChange{ 484 AccountAddress: txSender, 485 LightTokenAddress: lightTokenAddress, 486 LT: lightToken, 487 ChangeBalance: staking.Value, 488 ChangeType: types.UnStake, 489 ChangeStaking: staking, 490 }) 491 err = vdposContext.UpdateLightTokenAccount(lightTokenChanges) 492 if err != nil { 493 return err 494 } 495 496 return nil 497 } 498 499 func (v *Vdpos) processEventInsteadRegularLightToken(tx *types.Transaction, txSender common.Address, blockNum *big.Int, vdposContext *types.VdposContext) error { 500 stakingJson := new(types.StakingJson) 501 if err := json.Unmarshal(tx.Data(), stakingJson); err != nil { 502 return err 503 } 504 505 lightTokenAddress := stakingJson.LightTokenAddress 506 lockHeights := stakingJson.LockHeights 507 value := tx.Value() 508 txReceiver := *tx.To() 509 510 // first update lightTokenTrie 511 lightToken, err := vdposContext.UpdateLightTokenByTotalStakings(lightTokenAddress, value, types.Add) 512 if err != nil { 513 return err 514 } 515 516 // second update lightTokenAccountTrie 517 lightTokenChanges := new(types.LightTokenChanges) 518 lightTokenChanges.LTCs = append(lightTokenChanges.LTCs, &types.LightTokenChange{ 519 AccountAddress: txSender, 520 LightTokenAddress: lightTokenAddress, 521 LT: lightToken, 522 ChangeBalance: value, 523 ChangeType: types.Sub, 524 }, &types.LightTokenChange{ 525 AccountAddress: txReceiver, 526 LightTokenAddress: lightTokenAddress, 527 LT: lightToken, 528 ChangeBalance: value, 529 ChangeType: types.Add, 530 }, &types.LightTokenChange{ 531 AccountAddress: txReceiver, 532 LightTokenAddress: lightTokenAddress, 533 LT: lightToken, 534 ChangeBalance: value, 535 ChangeType: types.Stake, 536 ChangeStaking: &types.Staking{ 537 Hash: tx.Hash(), 538 StartHeight: blockNum, 539 LockHeights: lockHeights, 540 Value: value, 541 }, 542 }) 543 err = vdposContext.UpdateLightTokenAccount(lightTokenChanges) 544 if err != nil { 545 return err 546 } 547 548 return nil 549 }