github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/d_select.go (about)

     1  package core
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math"
     7  	"math/rand"
     8  	"os"
     9  	"time"
    10  
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"github.com/ethereum/go-ethereum/consensus/podc"
    13  	"github.com/ethereum/go-ethereum/log"
    14  	"github.com/ethereum/go-ethereum/qmanager/global"
    15  	"github.com/ethereum/go-ethereum/qmanager/utils"
    16  )
    17  
    18  //var ExtraDataLength int = 0  //int value is zero,
    19  
    20  func (c *core) sendDSelect() {
    21  	log.Debug("sendDSelect")
    22  	logger := c.logger.New("state", c.state)
    23  	var extra [7]common.ValidatorInfo // 최소 7개 노드에서 추가?  기동시 최소 7개 이상 띄워야함.
    24  	//var extra [50]ValidatorInfo  //debugging... 7 -> 50 ,, logical bug. 임시로 50개,, 나중에 수정할 것.
    25  	flag := false
    26  
    27  	for i, v := range c.valSet.List() {
    28  		validatorInfo := common.ValidatorInfo{}
    29  		validatorInfo.Address = v.Address()
    30  		validatorInfo.Qrnd = rand.Uint64()
    31  
    32  		if i == 0 {
    33  			if !c.valSet.IsProposer(v.Address()) {
    34  				validatorInfo.Tag = common.Coordinator
    35  			} else {
    36  				flag = true
    37  			}
    38  		} else if i == 1 {
    39  			if flag {
    40  				validatorInfo.Tag = common.Coordinator
    41  			}
    42  		} else {
    43  			validatorInfo.Tag = common.Candidate
    44  		}
    45  
    46  		extra[i] = validatorInfo
    47  	}
    48  
    49  	extraDataJson, err := json.Marshal(extra)
    50  	if err != nil {
    51  		logger.Error("Failed to encode JSON", err)
    52  	}
    53  
    54  	c.broadcast(&message{
    55  		Code: msgDSelect,
    56  		Msg:  extraDataJson,
    57  	})
    58  }
    59  
    60  func (c *core) sendExtraDataRequest() {
    61  	//c.send(&message{
    62  	//	Code: msgExtraDataRequest,
    63  	//	Msg: []byte("extra data request testing."),
    64  	//}, c.qmanager)
    65  
    66  	log.Info("Extra Data Request", "Status", "Requesting to Standalone Qmanager")
    67  
    68  	extra, err := utils.RequestExtraData(c.valSet.GetProposer().Address().String())
    69  
    70  	if err != nil {
    71  		log.Error("Extra Data Request Failure", "Error", err.Error())
    72  
    73  	} else {
    74  		//log.Info("Qmanager", "Recieved ExtraData", extra)
    75  
    76  		extraDataJson, err := json.Marshal(extra)
    77  		//log.Info("Qmanager", "Recieved extraDataJson", extraDataJson)
    78  		log.Info("Extra Data Request", "Status", "Recieved ExtraData")
    79  
    80  		if err != nil {
    81  			log.Error("Failed to encode", "extra data", extra)
    82  		}
    83  		c.ExtraDataLength = len(extra)
    84  
    85  		c.broadcast(&message{
    86  			Code: msgDSelect,
    87  			Msg:  extraDataJson,
    88  		})
    89  	}
    90  }
    91  
    92  func (c *core) sendCoordinatorDecide() {
    93  	log.Debug("sendCoordinatorDecide")
    94  	coordinatorData := c.valSet.GetProposer()
    95  	encodedCoordinatorData, err := Encode(&coordinatorData)
    96  
    97  	if err != nil {
    98  		log.Error("Failed to encode", "extra data", coordinatorData)
    99  		return
   100  	}
   101  
   102  	c.multicast(&message{
   103  		Code: msgCoordinatorDecide,
   104  		Msg:  encodedCoordinatorData,
   105  	}, c.GetValidatorListExceptQman())
   106  }
   107  
   108  func (c *core) sendRacing(addr common.Address) {
   109  	log.Debug("sendRacing")
   110  	c.send(&message{
   111  		Code: msgRacing,
   112  		Msg:  []byte("racing testing"),
   113  	}, addr)
   114  }
   115  
   116  func (c *core) sendCandidateDecide() {
   117  	log.Debug("sendCandidateDecide")
   118  
   119  	// var addrs []common.Address
   120  	// for _, val := range c.voteSet.List() {
   121  	// 	addrs = append(addrs, val.Address())
   122  	// }
   123  
   124  	// enc, err := rlp.EncodeToBytes(addrs)
   125  	// if err != nil {
   126  	// 	log.Error("Rlp encode error", "err", err)
   127  	// 	return
   128  	// }
   129  
   130  	c.multicast(&message{
   131  		Code: msgCandidateDecide,
   132  		Msg:  []byte("Candidate decide testing"),
   133  		//Msg: enc,
   134  	}, c.GetValidatorListExceptQman())
   135  	// c.multicast(&message{
   136  	// 	Code: msgCandidateDecide,
   137  	// 	//Msg:  []byte("Candidate decide testing"),
   138  	// 	Msg: enc,
   139  	// }, addrs)
   140  }
   141  
   142  //D-Select msg
   143  func (c *core) handleSentExtraData(msg *message, src podc.Validator) error {
   144  	// Decode d-select message
   145  	var extraData common.ValidatorInfos
   146  	if err := json.Unmarshal(msg.Msg, &extraData); err != nil {
   147  		log.Error("JSON Decode Error", "Err", err)
   148  		log.Info("Decode Error")
   149  		return errFailedDecodePrepare
   150  	}
   151  	c.ExtraDataLength = len(extraData)
   152  
   153  	c.broadcast(&message{
   154  		Code: msgDSelect,
   155  		Msg:  msg.Msg,
   156  	})
   157  
   158  	return nil
   159  }
   160  
   161  func (c *core) handleDSelect(msg *message, src podc.Validator) error {
   162  	log.Info("4. Get extra data and start d-select", "elapsed", common.PrettyDuration(time.Since(c.intervalTime)))
   163  	c.racingFlag = false
   164  	c.count = 0
   165  	c.intervalTime = time.Now()
   166  
   167  	// Decode d-select message
   168  	var extraData []common.ValidatorInfo
   169  
   170  	if err := json.Unmarshal(msg.Msg, &extraData); err != nil {
   171  		log.Error("JSON Decode Error", "Err", err)
   172  		return errFailedDecodePrepare
   173  	}
   174  
   175  	log.Debug("handleDSelect 1", "len(extraData)", len(extraData), "extraData", extraData)
   176  
   177  	nodename, err := os.Getwd()
   178  	if err != nil {
   179  		log.Debug("handleDSelect", "current nodename", nodename, "err", err)
   180  	}
   181  
   182  	var QRND uint64
   183  	//var vaddrs []common.Address
   184  	// var saddrs []common.Address
   185  	// scount := 0
   186  	for _, v := range extraData {
   187  		if v.Address == c.address {
   188  			c.tag = v.Tag
   189  			QRND = v.Qrnd
   190  		}
   191  		// if v.Tag == common.Senator || v.Tag == common.Coordinator {
   192  		// 	saddrs = append(saddrs, v.Address)
   193  		// 	scount++
   194  		// }
   195  		//vaddrs = append(vaddrs, v.Address)
   196  	}
   197  
   198  	//c.valSet = validator.NewSet(vaddrs, c.config.ProposerPolicy)
   199  	// c.voteSet = validator.NewSet(saddrs, c.config.ProposerPolicy)
   200  	// c.agreeCriteria = int((float64(scount)+math.Ceil(float64(scount)*float64(1.08)))*2/3) + 1
   201  
   202  	log.Debug("handleDSelect 2", "c.address", c.address, "c.tag", c.tag, "QRND", QRND)
   203  
   204  	if c.tag == common.Coordinator {
   205  		//QRNDArray := make([]byte, 8)
   206  		//binary.LittleEndian.PutUint64(QRNDArray, QRND)
   207  
   208  		c.ExtraDataLength = len(extraData)
   209  		c.criteria = 29
   210  
   211  		isCoordinator, err := utils.CoordinatorConfirmation(global.RequestCoordiStruct{QRND: QRND})
   212  		if err != nil {
   213  			log.Error("Coordinator Confirm Failure", "Error", err.Error())
   214  		}
   215  		if isCoordinator {
   216  			var err error
   217  			log.Info(fmt.Sprintf("I am Coordinator! ExtraDataLength %d", c.ExtraDataLength)) //grep -r 'I am Coordinator!' *.log
   218  			if c.ExtraDataLength != 0 {
   219  				c.criteria = math.Ceil(((float64(c.ExtraDataLength) - 1.00) * float64(0.51))) //Ceil.. >= 수 리턴.
   220  				// c.criteria = math.Ceil(float64(scount) * float64(1.08)) // Parliamentarian 52% = Senator*52/48, racing criteria
   221  			} else {
   222  				log.Error("ExtraDataLength has problem")
   223  				//utils.Fatalf("ExtraDataLength has problem)
   224  				return err
   225  			}
   226  
   227  			c.sendCoordinatorDecide()
   228  		}
   229  
   230  	} else {
   231  		c.ExtraDataLength = 0
   232  		c.criteria = 0
   233  	}
   234  	log.Debug("handleDSelect 3", "c.criteria", c.criteria, "c.ExtraDataLength", c.ExtraDataLength)
   235  
   236  	return nil
   237  }
   238  
   239  func (c *core) handleCoordinatorConfirm(msg *message, src podc.Validator) error {
   240  	var err error
   241  	log.Info(fmt.Sprintf("I am Coordinator! ExtraDataLength %d", c.ExtraDataLength)) //grep -r 'I am Coordinator!' *.log
   242  	if c.ExtraDataLength != 0 {
   243  		c.criteria = math.Ceil(((float64(c.ExtraDataLength) - 1.00) * float64(0.51))) //Ceil.. >= 수 리턴.
   244  	}
   245  	if c.ExtraDataLength == 0 {
   246  		log.Info("ExtraDataLength has problem")
   247  		//utils.Fatalf("ExtraDataLength has problem)
   248  		return err
   249  	}
   250  
   251  	log.Info("c.criteria=", "c.criteria", c.criteria)
   252  	c.sendCoordinatorDecide()
   253  
   254  	return nil
   255  }
   256  
   257  func (c *core) handleCoordinatorDecide(msg *message, src podc.Validator) error {
   258  	log.Debug("handleCoordinatorDecide", "extra", c.ExtraDataLength, "criteria", c.criteria)
   259  	// if c.tag != common.Coordinator {
   260  	if c.tag != common.Coordinator || c.ExtraDataLength == 0 { //TODO-REAP: workaround for disappeared racing msg
   261  		// if c.tag == common.Candidate { //TODO-REAP: workaround for disappeared racing msg
   262  		log.Debug("handleCoordinatorDecide - send racing", "extra", c.ExtraDataLength, "criteria", c.criteria)
   263  		c.sendRacing(src.Address()) //레이싱 시작 메시지 전송
   264  	}
   265  
   266  	return nil
   267  }
   268  
   269  func (c *core) handleRacing(msg *message, src podc.Validator) error {
   270  	c.racingMu.Lock()
   271  	defer c.racingMu.Unlock()
   272  	if c.tag == common.Coordinator {
   273  		c.count = c.count + 1
   274  		log.Debug("handleRacing 1", "c.count", c.count)
   275  		// if c.count <= uint(c.criteria) && !c.racingFlag {
   276  		// 	c.voteSet.AddValidator(src.Address())
   277  		// }
   278  		if c.count >= uint(c.criteria) && !c.racingFlag {
   279  			log.Debug("handleRacing 2", "c.count", c.count, "c.criteria", c.criteria, "c.racingFlag", c.racingFlag)
   280  			c.racingFlag = true
   281  			// send msg with voteSet list
   282  			c.sendCandidateDecide()
   283  		}
   284  	}
   285  
   286  	return nil
   287  }
   288  
   289  func (c *core) handleCandidateDecide(msg *message, src podc.Validator) error { //커밋단계로 진입
   290  	log.Debug("handleCandidateDecide", "c.state", c.state)
   291  	if c.state == StatePreprepared {
   292  		log.Info("5. Racing complete and d-select finished.", "elapsed", common.PrettyDuration(time.Since(c.intervalTime)))
   293  		//decode msg
   294  		// var addrs []common.Address
   295  		// err := rlp.DecodeBytes(msg.Msg, &addrs)
   296  		// if err != nil {
   297  		// 	log.Error("Rlp decode error", "err", err)
   298  		// 	return err
   299  		// }
   300  		// for _, addr := range addrs {
   301  		// 	if c.address == addr {
   302  		// 		c.intervalTime = time.Now()
   303  		// 		c.setState(StateDSelected) //D-selected 상태로 설정하고, 커밋 상태로 진입.
   304  		// 		c.sendDCommit()            // msgCommit 를 통하여, 메시지핸들러에서, handleDCommit를 실행, 여기서 c.verifyDCommit에서 inconsistent 발생,
   305  		// 		break
   306  		// 	}
   307  		// }
   308  		c.intervalTime = time.Now()
   309  		c.setState(StateDSelected) //D-selected 상태로 설정하고, 커밋 상태로 진입.
   310  		c.sendDCommit()            // msgCommit 를 통하여, 메시지핸들러에서, handleDCommit를 실행, 여기서 c.verifyDCommit에서 inconsistent 발생,
   311  	}
   312  
   313  	return nil
   314  }