diff --git a/contracts/randomize/randomize_test.go b/contracts/randomize/randomize_test.go index e800afc8cf..172fbf8b04 100644 --- a/contracts/randomize/randomize_test.go +++ b/contracts/randomize/randomize_test.go @@ -105,29 +105,21 @@ func TestSendTxRandomizeSecretAndOpening(t *testing.T) { backend.Commit() // Get randomize secret from SC. - secretsArr, err := randomizeContract.GetSecret(acc1Addr) - if err != nil { - t.Fatalf("Can't get secret from SC: %v", err) - } - if len(secretsArr) <= 0 { - t.Error("Empty get secrets from SC", err) - } - - // Decrypt randomize from SC. secrets, err := randomizeContract.GetSecret(acc1Addr) if err != nil { t.Error("Fail get secrets from randomize", err) } + if len(secrets) <= 0 { + t.Error("Empty get secrets from SC", err) + } + // Decrypt randomize from SC. opening, err := randomizeContract.GetOpening(acc1Addr) if err != nil { t.Fatalf("Can't get secret from SC: %v", err) } - randomizes, err := contracts.DecryptRandomizeFromSecretsAndOpening(secrets, opening) - t.Log("randomizes", randomizes) + randomize, err := contracts.DecryptRandomizeFromSecretsAndOpening(secrets, opening) + t.Log("randomize", randomize) if err != nil { t.Error("Can't decrypt secret and opening", err) } - if len(randomizes) != 901 { - t.Error("Randomize length not match", "length", len(randomizes)) - } } \ No newline at end of file diff --git a/contracts/utils.go b/contracts/utils.go index 262db29596..f5e0bf8b69 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -24,7 +24,6 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/pkg/errors" "io" - "math" "math/big" "math/rand" "strconv" @@ -38,9 +37,10 @@ const ( RewardFoundationPercent = 10 HexSetSecret = "34d38600" HexSetOpening = "e11f5ba2" - EpocBlockSecret = 950 - EpocBlockOpening = 980 - EpocBlockRandomize = 900 + EpocBlockSecret = 20 + EpocBlockOpening = 30 + EpocBlockRandomize = 50 + MaxMasternodes = 150 M2ByteLength = 4 extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal @@ -153,16 +153,13 @@ func CreateTxSign(blockNumber *big.Int, blockHash common.Hash, nonce uint64, blo // Send secret key into randomize smartcontract. func BuildTxSecretRandomize(nonce uint64, randomizeAddr common.Address, epocNumber uint64, randomizeKey []byte) (*types.Transaction, error) { data := common.Hex2Bytes(HexSetSecret) - secretMax := math.Round(float64(epocNumber / 10)) - secrets := Shuffle(NewSlice(0, int64(secretMax), 1)) + rand.Seed(time.Now().UnixNano()) + secretNumb := rand.Intn(int(epocNumber)) // Append randomize suffix in -1, 0, 1. - arrSuffix := []int64{-1, 1} - rand.Seed(time.Now().UnixNano()) - randIndex := rand.Intn(len(arrSuffix)) - secrets = append(secrets, arrSuffix[randIndex]) - + secrets := []int64{int64(secretNumb)} sizeOfArray := int64(32) + // Build extra data for tx with first position is size of array byte and second position are length of array byte. arrSizeOfSecrets := common.LeftPadBytes(new(big.Int).SetInt64(sizeOfArray).Bytes(), 32) arrLengthOfSecrets := common.LeftPadBytes(new(big.Int).SetInt64(int64(len(secrets))).Bytes(), 32) @@ -204,7 +201,7 @@ func GetSignersFromContract(addrBlockSigner common.Address, client bind.Contract } // Get random from randomize contract. -func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) ([]int64, error) { +func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) (int64, error) { randomize, err := randomizeContract.NewXDCRandomize(common.HexToAddress(common.RandomizeSMC), client) if err != nil { log.Error("Fail to get instance of randomize", "error", err) @@ -223,26 +220,29 @@ func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common } // Generate m2 listing from randomize array. -func GenM2FromRandomize(randomizes [][]int64) ([]int64, error) { - // Separate array. - arrRandomizes := TransposeMatrix(randomizes) - lenRandomize := len(arrRandomizes) - arrayA := arrRandomizes[:lenRandomize-2] - arrayB := arrRandomizes[lenRandomize-1:] - - matrixResult, err := DotMatrix(arrayA, arrayB) - if err != nil { - log.Error("Fail to dot matrix", "error", err) - - return nil, err +func GenM2FromRandomize(randomizes []int64) ([]int64, error) { + blockValidator := NewSlice(int64(0), MaxMasternodes, 1) + randIndexs := make([]int64, MaxMasternodes) + total := int64(0) + var temp int64 = 0 + for _, j := range randomizes { + total += j } - lenMasternode := len(arrayB[0]) - result := make([]int64, lenRandomize) - for i, v := range matrixResult { - result[i] = int64(math.Abs(float64(v))) % int64(lenMasternode) + rand.Seed(total) + for i := len(blockValidator) - 1; i >= 0; i-- { + blockLength := len(blockValidator) - 1 + if blockLength <= 1 { + blockLength = 1 + } + randomIndex := int64(rand.Intn(blockLength)) + temp = blockValidator[randomIndex] + blockValidator[randomIndex] = blockValidator[i] + blockValidator[i] = temp + blockValidator = append(blockValidator[:i], blockValidator[i+1:]...) + randIndexs[i] = temp } - return result, nil + return randIndexs, nil } // Get validators from m2 array integer. @@ -284,12 +284,10 @@ func DecodeValidatorsHexData(validatorsStr string) ([]int64, error) { } // Decrypt randomize from secrets and opening. -func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte) ([]int64, error) { - var random []int64 - var completedRandomize []int64 - random = make([]int64, len(secrets)) +func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte) (int64, error) { + var random int64 if len(secrets) > 0 { - for i, secret := range secrets { + for _, secret := range secrets { trimSecret := bytes.TrimLeft(secret[:], "\x00") decryptSecret := Decrypt(opening[:], string(trimSecret)) if isInt(decryptSecret) { @@ -297,26 +295,12 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte) if err != nil { log.Error("Can not convert string to integer", "error", err) } - random[i] = int64(intNumber) + random = int64(intNumber) } } } - // Generate full randomize. - randomMax := len(random) - 1 - if randomMax > 0 { - for i, randNumber := range random { - if i < randomMax { - for j := 0; j < 10; j++ { - completedRandomize = append(completedRandomize, randNumber*10+int64(j)) - } - } - } - completedRandomize = append(completedRandomize, random[randomMax]) - } - log.Error("random", "completedRandomize", completedRandomize, "randomMax", randomMax) - - return completedRandomize, nil + return random, nil } // Calculate reward for reward checkpoint. @@ -568,33 +552,6 @@ func isInt(strNumber string) bool { } } -// Helper function for transpose matrix. -func TransposeMatrix(x [][]int64) [][]int64 { - out := make([][]int64, len(x[0])) - for i := 0; i < len(x); i += 1 { - for j := 0; j < len(x[0]); j += 1 { - out[j] = append(out[j], x[i][j]) - } - } - return out -} - -// Helper function for multiplication matrix. -func DotMatrix(x, y [][]int64) ([]int64, error) { - if len(x[0]) != len(y[0]) { - return nil, errors.New("Can't do matrix multiplication.") - } - - out := make([]int64, len(x)) - for i := 0; i < len(x); i += 1 { - for j := 0; j < len(y[0]); j += 1 { - out[i] += x[i][j] * y[0][j] - } - } - - return out, nil -} - // Get masternodes address from checkpoint Header. func GetMasternodesFromCheckpointHeader(checkpointHeader *types.Header) []common.Address { masternodes := make([]common.Address, (len(checkpointHeader.Extra)-extraVanity-extraSeal)/common.AddressLength) diff --git a/contracts/utils_test.go b/contracts/utils_test.go index cb8764c543..18ec9d5789 100644 --- a/contracts/utils_test.go +++ b/contracts/utils_test.go @@ -135,40 +135,6 @@ func TestEncryptDecrypt(t *testing.T) { t.Log("Encrypt", encrypt, "Test", string(randomByte), "Decrypt", decrypt, "trim", string(bytes.TrimLeft([]byte(decrypt), "\x00"))) } -func TestTransposeMatrix(t *testing.T) { - a := [][]int64{ - {0, 1, 2, 3, 4}, - {4, 5, 6, 7, 8}, - } - b := [][]int64{ - {0, 4}, - {1, 5}, - {2, 6}, - {3, 7}, - {4, 8}, - } - if !isArrayEqual(b, TransposeMatrix(a)) { - t.Errorf("Fail to transpose matrix %v - %v", a, TransposeMatrix(a)) - } -} - -func TestMultiMatrix(t *testing.T) { - a := make([][]int64, 6) - b := [][]int64{ - {1, -1, -1, 1, 1, -1}, - } - for i := 0; i < len(b[0]); i++ { - a[i] = Shuffle(NewSlice(0, 6, 1)) - } - c, err := DotMatrix(a, b) - if err != nil { - t.Error("Fail to test dot matrix", err) - } - if len(a[0]) != len(c) { - t.Errorf("Fail to test dot matrix result %v - %v - %v", a, b, c) - } -} - func isArrayEqual(a [][]int64, b [][]int64) bool { if len(a) != len(b) { return false @@ -185,25 +151,28 @@ func isArrayEqual(a [][]int64, b [][]int64) bool { // Unit test for func TestGenM2FromRandomize(t *testing.T) { - a := [][]int64{ - {37, 23, 17, 45, 38, 8, 21, 28, 15, 41, 1, 25, 4, 30, 31, 0, 9, 16, 46, 13, 36, 7, 19, 27, 47, 32, 22, 3, 20, 33, 2, 35, 49, 6, 42, 34, 44, 10, 29, 26, 12, 43, 48, 24, 40, 14, 18, 39, 5, 11, 1}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {28, 16, 13, 31, 32, 36, 44, 14, 37, 33, 3, 23, 17, 46, 35, 30, 45, 27, 9, 41, 7, 19, 10, 24, 5, 34, 29, 18, 21, 15, 0, 2, 25, 39, 11, 4, 22, 6, 48, 42, 12, 26, 1, 47, 43, 20, 40, 38, 8, 49, -1}, + var a []int64 + for i := 0; i <= 10; i++ { + rand.Seed(time.Now().UTC().UnixNano()) + a = append(a, int64(rand.Intn(9999))) } b, err := GenM2FromRandomize(a) - t.Log("randomize", b) + t.Log("randomize", b, "len", len(b)) if err != nil { t.Error("Fail to test gen m2 for randomize.", err) } - c := []int64{0, 1, 1, 2, 0, 1, 2, 2, 1, 2, 2, 2, 1, 1, 1, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 2, 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 2, 2, 2, 0, 0, 1, 1, 0, 0, 0} - if !isArrayEqual([][]int64{b}, [][]int64{c}) { - t.Errorf("Fail to get m2 result %v", b) + // Test Permutation Without Fixed-point. + M1List := NewSlice(int64(0), MaxMasternodes, 1) + for i, m1 := range M1List { + if m1 == b[i] { + t.Errorf("Error check Permutation Without Fixed-point %v - %v - %v", i, b[i], a) + } } } // Unit test for validator m2. func TestBuildValidatorFromM2(t *testing.T) { - a := []int64{0, 1, 1, 2, 0, 1, 2, 128, 150, 2, 2, 2, 1, 1, 1, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 2, 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 2, 2, 2, 0, 0, 1, 1, 0, 0, 0} + a := []int64{84, 58, 27, 96, 127, 60, 136, 20, 121, 31, 87, 85, 40, 120, 149, 109, 141, 145, 11, 110, 147, 35, 76, 46, 34, 108, 72, 103, 102, 12, 23, 47, 70, 86, 125, 112, 128, 13, 130, 98, 126, 62, 132, 111, 134, 6, 106, 67, 24, 91, 101, 50, 94, 43, 77, 73, 129, 71, 51, 10, 92, 29, 80, 95, 33, 100, 124, 75, 38, 133, 79, 83, 61, 36, 122, 99, 16, 28, 18, 116, 140, 97, 119, 82, 148, 48, 56, 32, 93, 107, 69, 68, 123, 81, 22, 137, 25, 115, 44, 8, 42, 131, 143, 17, 55, 89, 9, 15, 19, 59, 146, 54, 5, 30, 41, 144, 117, 1, 104, 49, 105, 45, 88, 78, 74, 135, 0, 21, 57, 3, 66, 52, 63, 138, 4, 114, 37, 118, 14, 2, 26, 7, 65, 139, 39, 64, 90, 142, 53, 113} b := BuildValidatorFromM2(a) c := ExtractValidatorsFromBytes(b) if !isArrayEqual([][]int64{a}, [][]int64{c}) { @@ -218,7 +187,8 @@ func TestDecodeValidatorsHexData(t *testing.T) { if err != nil { t.Error("Fail to decode validator from hex string", err) } - c := []int64{1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 2, 0, 1, 2, 0, 1, 2, 0, 1, 0, 0} if !isArrayEqual([][]int64{b}, [][]int64{c}) { + c := []int64{1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 2, 0, 1, 2, 0, 1, 2, 0, 1, 0, 0} + if !isArrayEqual([][]int64{b}, [][]int64{c}) { t.Errorf("Fail to get m2 result %v", b) } t.Log("b", b) diff --git a/eth/backend.go b/eth/backend.go index fb3e29bfd5..c873ef1201 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -255,7 +255,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { // Check m2 exists on chaindb. // Get secrets and opening at epoc block checkpoint. if number > 0 && number%contracts.EpocBlockRandomize == 0 { - var candidates [][]int64 + var candidates []int64 // Get signers from snapshot. snap, err := c.GetSnapshot(eth.blockchain, chain.CurrentHeader()) if err != nil { @@ -270,9 +270,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if err != nil { log.Error("Fail to get random m2 from contract.", "error", err) } - if random != nil { - candidates = append(candidates, random) - } + candidates = append(candidates, random) } } @@ -284,7 +282,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if len(m2) > 0 { header.Validators = contracts.BuildValidatorFromM2(m2) } - log.Debug("list m2", "M2", m2) } return nil