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  }