aboutsummaryrefslogtreecommitdiffstats
path: root/core/test/state-change-request.go
diff options
context:
space:
mode:
authorMission Liao <mission.liao@dexon.org>2018-11-07 16:11:17 +0800
committerGitHub <noreply@github.com>2018-11-07 16:11:17 +0800
commit766e6aac32b8f97934833c06814c37dbdd9b7ae2 (patch)
treeaac3c79c6db2c5c32de3519888b2e1253eb0fceb /core/test/state-change-request.go
parentbcdc444319ca9fe219f27e818ab9ec863d6757ea (diff)
downloadtangerine-consensus-766e6aac32b8f97934833c06814c37dbdd9b7ae2.tar
tangerine-consensus-766e6aac32b8f97934833c06814c37dbdd9b7ae2.tar.gz
tangerine-consensus-766e6aac32b8f97934833c06814c37dbdd9b7ae2.tar.bz2
tangerine-consensus-766e6aac32b8f97934833c06814c37dbdd9b7ae2.tar.lz
tangerine-consensus-766e6aac32b8f97934833c06814c37dbdd9b7ae2.tar.xz
tangerine-consensus-766e6aac32b8f97934833c06814c37dbdd9b7ae2.tar.zst
tangerine-consensus-766e6aac32b8f97934833c06814c37dbdd9b7ae2.zip
test: make StateChangeRequest broadcast-able (#305)
Make `test.StateChangeRequest` behaves like tx on ethereum: - Can be broadcasted and cached in a pool. - Uniquely indexed, and be removed after applied. Changes: - Make cloneDKGx functions in test.State as utilities. - Add hash and timestamp fields to test.StateChangeRequest. - Add two methods to test.State: - PackOwnRequests would pack all pending change requests owned by this instance as byte slice, and move them to global pending requests pool. - AddRequestsFromOthers would add pending change requests from others to global pending requests pool. - The method State.PackRequests now would pack requests in global pending requests pool. - The method State.Apply would remove corresponding StateChangeRequest by hash.
Diffstat (limited to 'core/test/state-change-request.go')
-rw-r--r--core/test/state-change-request.go135
1 files changed, 135 insertions, 0 deletions
diff --git a/core/test/state-change-request.go b/core/test/state-change-request.go
new file mode 100644
index 0000000..0f49db0
--- /dev/null
+++ b/core/test/state-change-request.go
@@ -0,0 +1,135 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus library is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// The dexon-consensus library is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the dexon-consensus library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package test
+
+import (
+ "time"
+
+ "github.com/dexon-foundation/dexon-consensus/common"
+ "github.com/dexon-foundation/dexon-consensus/core/crypto"
+ typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg"
+ "github.com/dexon-foundation/dexon/rlp"
+)
+
+// StateChangeType is the type of state change request.
+type StateChangeType uint8
+
+// Types of state change.
+const (
+ StateChangeNothing StateChangeType = iota
+ // DKG & CRS
+ StateAddCRS
+ StateAddDKGComplaint
+ StateAddDKGMasterPublicKey
+ StateAddDKGFinal
+ // Configuration related.
+ StateChangeNumChains
+ StateChangeLambdaBA
+ StateChangeLambdaDKG
+ StateChangeRoundInterval
+ StateChangeMinBlockInterval
+ StateChangeMaxBlockInterval
+ StateChangeK
+ StateChangePhiRatio
+ StateChangeNotarySetSize
+ StateChangeDKGSetSize
+ // Node set related.
+ StateAddNode
+)
+
+// StateChangeRequest carries information of state change request.
+type StateChangeRequest struct {
+ Type StateChangeType `json:"type"`
+ Payload interface{} `json:"payload"`
+ // The purpose of these fields are aiming to provide an unique ID for each
+ // change request.
+ Hash common.Hash
+ Timestamp uint64
+}
+
+// this structure is mainly for marshalling for StateChangeRequest.
+type rawStateChangeRequest struct {
+ Type StateChangeType
+ Payload rlp.RawValue
+ Hash common.Hash
+ Timestamp uint64
+}
+
+// NewStateChangeRequest constructs an StateChangeRequest instance.
+func NewStateChangeRequest(
+ t StateChangeType, payload interface{}) *StateChangeRequest {
+ now := uint64(time.Now().UTC().UnixNano())
+ b, err := rlp.EncodeToBytes(struct {
+ Type StateChangeType
+ Payload interface{}
+ Timestamp uint64
+ }{t, payload, now})
+ if err != nil {
+ panic(err)
+ }
+ return &StateChangeRequest{
+ Hash: crypto.Keccak256Hash(b),
+ Type: t,
+ Payload: payload,
+ Timestamp: now,
+ }
+}
+
+// Clone a StateChangeRequest instance.
+func (req *StateChangeRequest) Clone() (copied *StateChangeRequest) {
+ copied = &StateChangeRequest{
+ Type: req.Type,
+ Hash: req.Hash,
+ Timestamp: req.Timestamp,
+ }
+ // NOTE: The cloned DKGx structs would be different from sources in binary
+ // level, thus would produce different hash from the source.
+ // I don't want different hash for source/copied requests thus would
+ // copy the hash from source directly.
+ switch req.Type {
+ case StateAddNode:
+ srcBytes := req.Payload.([]byte)
+ copiedBytes := make([]byte, len(srcBytes))
+ copy(copiedBytes, srcBytes)
+ req.Payload = copiedBytes
+ case StateAddCRS:
+ crsReq := req.Payload.(*crsAdditionRequest)
+ copied.Payload = &crsAdditionRequest{
+ Round: crsReq.Round,
+ CRS: crsReq.CRS,
+ }
+ case StateAddDKGFinal:
+ copied.Payload = cloneDKGFinalize(req.Payload.(*typesDKG.Finalize))
+ case StateAddDKGMasterPublicKey:
+ copied.Payload = cloneDKGMasterPublicKey(
+ req.Payload.(*typesDKG.MasterPublicKey))
+ case StateAddDKGComplaint:
+ copied.Payload = cloneDKGComplaint(req.Payload.(*typesDKG.Complaint))
+ default:
+ copied.Payload = req.Payload
+ }
+ return
+}
+
+// Equal checks equality between two StateChangeRequest.
+func (req *StateChangeRequest) Equal(other *StateChangeRequest) error {
+ if req.Hash == other.Hash {
+ return nil
+ }
+ return ErrStatePendingChangesNotEqual
+}