mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
Get randomize m2 offer from validators in smart contract.
Fixed get and build randomize for m2 from smart contract. Fixed get m2 list from smart contract randomize.
This commit is contained in:
parent
9fa830c741
commit
ec764859fd
10 changed files with 669 additions and 34 deletions
|
|
@ -17,7 +17,7 @@ import (
|
||||||
const SafeMathABI = "[]"
|
const SafeMathABI = "[]"
|
||||||
|
|
||||||
// SafeMathBin is the compiled bytecode used for deploying new contracts.
|
// SafeMathBin is the compiled bytecode used for deploying new contracts.
|
||||||
const SafeMathBin = `0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146060604052600080fd00a165627a7a72305820b9407d48ebc7efee5c9f08b3b3a957df2939281f5913225e8c1291f069b900490029`
|
const SafeMathBin = `0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820a3f63b465e1cf25f306b1eb1efefc8dac3c38993a7340f69d8b470c3bf599ff30029`
|
||||||
|
|
||||||
// DeploySafeMath deploys a new Ethereum contract, binding an instance of SafeMath to it.
|
// DeploySafeMath deploys a new Ethereum contract, binding an instance of SafeMath to it.
|
||||||
func DeploySafeMath(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SafeMath, error) {
|
func DeploySafeMath(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SafeMath, error) {
|
||||||
|
|
@ -178,7 +178,7 @@ func (_SafeMath *SafeMathTransactorRaw) Transact(opts *bind.TransactOpts, method
|
||||||
const TomoRandomizeABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"getSecret\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_secret\",\"type\":\"bytes32[]\"}],\"name\":\"setSecret\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"randomNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"getOpening\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_opening\",\"type\":\"bytes32\"}],\"name\":\"setOpening\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_randomNumber\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"
|
const TomoRandomizeABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"getSecret\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_secret\",\"type\":\"bytes32[]\"}],\"name\":\"setSecret\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"randomNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"getOpening\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_opening\",\"type\":\"bytes32\"}],\"name\":\"setOpening\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_randomNumber\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"
|
||||||
|
|
||||||
// TomoRandomizeBin is the compiled bytecode used for deploying new contracts.
|
// TomoRandomizeBin is the compiled bytecode used for deploying new contracts.
|
||||||
const TomoRandomizeBin = `0x6060604052341561000f57600080fd5b604051602080610359833981016040528080516000555050610323806100366000396000f30060606040526004361061006c5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663284180fc811461007157806334d38600146100e3578063ccbac9f514610134578063d442d6cc14610159578063e11f5ba214610178575b600080fd5b341561007c57600080fd5b610090600160a060020a036004351661018e565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156100cf5780820151838201526020016100b7565b505050509050019250505060405180910390f35b34156100ee57600080fd5b610132600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061021295505050505050565b005b341561013f57600080fd5b61014761023f565b60405190815260200160405180910390f35b341561016457600080fd5b610147600160a060020a0360043516610245565b341561018357600080fd5b610132600435610260565b61019661027b565b6001600083600160a060020a0316600160a060020a0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561020657602002820191906000526020600020905b815481526001909101906020018083116101f1575b50505050509050919050565b600160a060020a033316600090815260016020526040902081805161023b92916020019061028d565b5050565b60005481565b600160a060020a031660009081526002602052604090205490565b600160a060020a033316600090815260026020526040902055565b60206040519081016040526000815290565b8280548282559060005260206000209081019282156102ca579160200282015b828111156102ca57825182556020909201916001909101906102ad565b506102d69291506102da565b5090565b6102f491905b808211156102d657600081556001016102e0565b905600a165627a7a7230582043a345787b9942e3361515ce1a0a4dbaab0ed6ce42c6ca0344119134351d9ffe0029`
|
const TomoRandomizeBin = `0x608060405234801561001057600080fd5b5060405160208061035b8339810160405251600055610327806100346000396000f30060806040526004361061006c5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663284180fc811461007157806334d38600146100ef578063ccbac9f514610146578063d442d6cc1461016d578063e11f5ba21461019b575b600080fd5b34801561007d57600080fd5b5061009f73ffffffffffffffffffffffffffffffffffffffff600435166101b3565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156100db5781810151838201526020016100c3565b505050509050019250505060405180910390f35b3480156100fb57600080fd5b50604080516020600480358082013583810280860185019096528085526101449536959394602494938501929182918501908490808284375094975061022d9650505050505050565b005b34801561015257600080fd5b5061015b610251565b60408051918252519081900360200190f35b34801561017957600080fd5b5061015b73ffffffffffffffffffffffffffffffffffffffff60043516610257565b3480156101a757600080fd5b5061014460043561027f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602090815260409182902080548351818402810184019094528084526060939283018282801561022157602002820191906000526020600020905b8154815260019091019060200180831161020c575b50505050509050919050565b336000908152600160209081526040909120825161024d92840190610291565b5050565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b33600090815260026020526040902055565b8280548282559060005260206000209081019282156102ce579160200282015b828111156102ce57825182556020909201916001909101906102b1565b506102da9291506102de565b5090565b6102f891905b808211156102da57600081556001016102e4565b905600a165627a7a7230582027c1c755e5d546967a2057a4338eb36cf7ec5972758d7f7a8427abdfc890bd590029`
|
||||||
|
|
||||||
// DeployTomoRandomize deploys a new Ethereum contract, binding an instance of TomoRandomize to it.
|
// DeployTomoRandomize deploys a new Ethereum contract, binding an instance of TomoRandomize to it.
|
||||||
func DeployTomoRandomize(auth *bind.TransactOpts, backend bind.ContractBackend, _randomNumber *big.Int) (common.Address, *types.Transaction, *TomoRandomize, error) {
|
func DeployTomoRandomize(auth *bind.TransactOpts, backend bind.ContractBackend, _randomNumber *big.Int) (common.Address, *types.Transaction, *TomoRandomize, error) {
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,23 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/contracts"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
epocNumber = int64(12)
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
addr = crypto.PubkeyToAddress(key.PublicKey)
|
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
byte0 = make([][32]byte, 2)
|
byte0 = make([][32]byte, epocNumber)
|
||||||
|
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||||
|
acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey)
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRandomize(t *testing.T) {
|
func TestRandomize(t *testing.T) {
|
||||||
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
|
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(100000000000000)}})
|
||||||
transactOpts := bind.NewKeyedTransactor(key)
|
transactOpts := bind.NewKeyedTransactor(key)
|
||||||
|
transactOpts.GasLimit = 1000000
|
||||||
|
|
||||||
randomizeAddress, randomize, err := DeployRandomize(transactOpts, contractBackend, big.NewInt(2))
|
randomizeAddress, randomize, err := DeployRandomize(transactOpts, contractBackend, big.NewInt(2))
|
||||||
t.Log("contract address", randomizeAddress.String())
|
t.Log("contract address", randomizeAddress.String())
|
||||||
|
|
@ -55,11 +61,88 @@ func TestRandomize(t *testing.T) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
contractBackend.ForEachStorageAt(ctx, randomizeAddress, nil, f)
|
contractBackend.ForEachStorageAt(ctx, randomizeAddress, nil, f)
|
||||||
|
|
||||||
s, err := randomize.SetSecret(byte0)
|
s, err := randomize.SetSecret(byte0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't get secret: %v", err)
|
t.Fatalf("can't set secret: %v", err)
|
||||||
}
|
}
|
||||||
t.Log("tx data", s)
|
t.Log("tx data", s)
|
||||||
contractBackend.Commit()
|
contractBackend.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSendTxRandomizeSecretAndOpening(t *testing.T) {
|
||||||
|
genesis := core.GenesisAlloc{acc1Addr: {Balance: big.NewInt(1000000000000)}}
|
||||||
|
backend := backends.NewSimulatedBackend(genesis)
|
||||||
|
backend.Commit()
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
transactOpts := bind.NewKeyedTransactor(acc1Key)
|
||||||
|
transactOpts.GasLimit = 4200000
|
||||||
|
epocNumber := uint64(99)
|
||||||
|
randomizeAddr, randomizeContract, err := DeployRandomize(transactOpts, backend, new(big.Int).SetInt64(0))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't deploy randomize SC: %v", err)
|
||||||
|
}
|
||||||
|
backend.Commit()
|
||||||
|
|
||||||
|
nonce := uint64(1)
|
||||||
|
randomizeKeyValue := contracts.RandStringByte(32)
|
||||||
|
tx, err := contracts.BuildTxSecretRandomize(nonce, randomizeAddr, epocNumber, randomizeKeyValue)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't create tx randomize secret: %v", err)
|
||||||
|
}
|
||||||
|
tx, err = types.SignTx(tx, signer, acc1Key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't sign tx randomize secret: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = backend.SendTransaction(ctx, tx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't send tx for create randomize secret: %v", err)
|
||||||
|
}
|
||||||
|
backend.Commit()
|
||||||
|
// Increment nonce.
|
||||||
|
nonce++
|
||||||
|
// Set opening.
|
||||||
|
tx, err = contracts.BuildTxOpeningRandomize(nonce, randomizeAddr, randomizeKeyValue)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't create tx randomize opening: %v", err)
|
||||||
|
}
|
||||||
|
tx, err = types.SignTx(tx, signer, acc1Key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't sign tx randomize opening: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = backend.SendTransaction(ctx, tx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't send tx for create randomize opening: %v", err)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Can't decrypt secret and opening", err)
|
||||||
|
}
|
||||||
|
if len(randomizes) != 991 {
|
||||||
|
t.Error("Randomize length not match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,34 @@
|
||||||
package contracts
|
package contracts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
cryptoRand "crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/contracts/blocksigner/contract"
|
"github.com/ethereum/go-ethereum/contracts/blocksigner/contract"
|
||||||
|
randomizeContract "github.com/ethereum/go-ethereum/contracts/randomize/contract"
|
||||||
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
|
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -36,6 +51,14 @@ const (
|
||||||
RewardMasterPercent = 40
|
RewardMasterPercent = 40
|
||||||
RewardVoterPercent = 50
|
RewardVoterPercent = 50
|
||||||
RewardFoundationPercent = 10
|
RewardFoundationPercent = 10
|
||||||
|
HexSetSecret = "34d38600"
|
||||||
|
HexSetOpening = "e11f5ba2"
|
||||||
|
EpocBlockSecret = 950
|
||||||
|
EpocBlockOpening = 980
|
||||||
|
EpocBlockRandomize = 900
|
||||||
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
type rewardLog struct {
|
type rewardLog struct {
|
||||||
|
|
@ -44,7 +67,7 @@ type rewardLog struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send tx sign for block number to smart contract blockSigner.
|
// Send tx sign for block number to smart contract blockSigner.
|
||||||
func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, manager *accounts.Manager, block *types.Block) error {
|
func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, manager *accounts.Manager, block *types.Block, chainDb ethdb.Database) error {
|
||||||
if chainConfig.Posv != nil {
|
if chainConfig.Posv != nil {
|
||||||
// Find active account.
|
// Find active account.
|
||||||
account := accounts.Account{}
|
account := accounts.Account{}
|
||||||
|
|
@ -64,9 +87,69 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
|
||||||
log.Error("Fail to create tx sign", "error", err)
|
log.Error("Fail to create tx sign", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add tx signed to local tx pool.
|
// Add tx signed to local tx pool.
|
||||||
pool.AddLocal(txSigned)
|
err = pool.AddLocal(txSigned)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to add tx sign to local pool.", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create secret tx.
|
||||||
|
blockNumber := block.Number().Uint64()
|
||||||
|
checkNumber := blockNumber % chainConfig.Posv.Epoch
|
||||||
|
// Generate random private key and save into chaindb.
|
||||||
|
randomizeKeyName := []byte("randomizeKey")
|
||||||
|
exist, _ := chainDb.Has(randomizeKeyName)
|
||||||
|
|
||||||
|
// Set secret for randomize.
|
||||||
|
if !exist && checkNumber > 0 && EpocBlockSecret <= checkNumber && EpocBlockOpening > checkNumber {
|
||||||
|
// Only process when private key empty in state db.
|
||||||
|
// Save randomize key into state db.
|
||||||
|
randomizeKeyValue := RandStringByte(32)
|
||||||
|
chainDb.Put(randomizeKeyName, randomizeKeyValue)
|
||||||
|
|
||||||
|
tx, err := BuildTxSecretRandomize(nonce, common.HexToAddress(common.RandomizeSMC), chainConfig.Posv.Epoch, randomizeKeyValue)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to get tx opening for randomize", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
txSigned, err := wallet.SignTx(account, tx, chainConfig.ChainId)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to create tx secret", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Add tx signed to local tx pool.
|
||||||
|
err = pool.AddLocal(txSigned)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to add tx secret to local pool.", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set opening for randomize.
|
||||||
|
if exist && checkNumber > 0 && EpocBlockOpening <= checkNumber && EpocBlockRandomize >= checkNumber {
|
||||||
|
randomizeKeyValue, err := chainDb.Get(randomizeKeyName)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to get randomize key from state db.", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := BuildTxOpeningRandomize(nonce, common.HexToAddress(common.RandomizeSMC), randomizeKeyValue)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to get tx opening for randomize", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
txSigned, err := wallet.SignTx(account, tx, chainConfig.ChainId)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to create tx opening", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Add tx to pool.
|
||||||
|
err = pool.AddLocal(txSigned)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to add tx opening to local pool.", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear randomize key in state db.
|
||||||
|
chainDb.Delete(randomizeKeyName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -82,6 +165,42 @@ func CreateTxSign(blockNumber *big.Int, blockHash common.Hash, nonce uint64, blo
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
|
||||||
|
// 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])
|
||||||
|
|
||||||
|
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)
|
||||||
|
inputData := append(data, arrSizeOfSecrets...)
|
||||||
|
inputData = append(inputData, arrLengthOfSecrets...)
|
||||||
|
for _, secret := range secrets {
|
||||||
|
encryptSecret := Encrypt(randomizeKey, new(big.Int).SetInt64(secret).String())
|
||||||
|
inputData = append(inputData, common.LeftPadBytes([]byte(encryptSecret), int(sizeOfArray))...)
|
||||||
|
}
|
||||||
|
tx := types.NewTransaction(nonce, randomizeAddr, big.NewInt(0), 4200000, big.NewInt(0), inputData)
|
||||||
|
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send opening to randomize SMC.
|
||||||
|
func BuildTxOpeningRandomize(nonce uint64, randomizeAddr common.Address, randomizeKey []byte) (*types.Transaction, error) {
|
||||||
|
data := common.Hex2Bytes(HexSetOpening)
|
||||||
|
inputData := append(data, randomizeKey...)
|
||||||
|
tx := types.NewTransaction(nonce, randomizeAddr, big.NewInt(0), 4200000, big.NewInt(0), inputData)
|
||||||
|
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get signers signed for blockNumber from blockSigner contract.
|
// Get signers signed for blockNumber from blockSigner contract.
|
||||||
func GetSignersFromContract(addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) {
|
func GetSignersFromContract(addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) {
|
||||||
blockSigner, err := contract.NewBlockSigner(addrBlockSigner, client)
|
blockSigner, err := contract.NewBlockSigner(addrBlockSigner, client)
|
||||||
|
|
@ -99,6 +218,122 @@ func GetSignersFromContract(addrBlockSigner common.Address, client bind.Contract
|
||||||
return addrs, nil
|
return addrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get random from randomize contract.
|
||||||
|
func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) ([]int64, error) {
|
||||||
|
randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to get instance of randomize", "error", err)
|
||||||
|
}
|
||||||
|
opts := new(bind.CallOpts)
|
||||||
|
secrets, err := randomize.GetSecret(opts, addrMasternode)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail get secrets from randomize", "error", err)
|
||||||
|
}
|
||||||
|
opening, err := randomize.GetOpening(opts, addrMasternode)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail get opening from randomize", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return DecryptRandomizeFromSecretsAndOpening(secrets, opening)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
lenMasternode := len(arrayB[0])
|
||||||
|
result := make([]int64, lenRandomize)
|
||||||
|
for i, v := range matrixResult {
|
||||||
|
result[i] = int64(math.Abs(float64(v))) % int64(lenMasternode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get validators from m2 array integer.
|
||||||
|
func BuildValidatorFromM2(listM2 []int64) []byte {
|
||||||
|
var validatorBytes []byte
|
||||||
|
for _, numberM2 := range listM2 {
|
||||||
|
// Convert number to byte.
|
||||||
|
m2Byte := common.LeftPadBytes([]byte(fmt.Sprintf("%d", numberM2)), M2ByteLength)
|
||||||
|
validatorBytes = append(validatorBytes, m2Byte...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return validatorBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract validators from byte array.
|
||||||
|
func ExtractValidatorsFromBytes(byteValidators []byte) []int64 {
|
||||||
|
lenValidator := len(byteValidators) / M2ByteLength
|
||||||
|
var validators []int64
|
||||||
|
for i := 0; i < lenValidator; i++ {
|
||||||
|
trimByte := bytes.Trim(byteValidators[i*M2ByteLength:(i+1)*M2ByteLength], "\x00")
|
||||||
|
intNumber, err := strconv.Atoi(string(trimByte))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Can not convert string to integer", "error", err)
|
||||||
|
}
|
||||||
|
validators = append(validators, int64(intNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
return validators
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode validator hex string.
|
||||||
|
func DecodeValidatorsHexData(validatorsStr string) ([]int64, error) {
|
||||||
|
validatorsByte, err := hexutil.Decode(validatorsStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExtractValidatorsFromBytes(validatorsByte), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
if len(secrets) > 0 {
|
||||||
|
for i, secret := range secrets {
|
||||||
|
trimSecret := bytes.TrimLeft(secret[:], "\x00")
|
||||||
|
decryptSecret := Decrypt(opening[:], string(trimSecret))
|
||||||
|
if isInt(decryptSecret) {
|
||||||
|
intNumber, err := strconv.Atoi(decryptSecret)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Can not convert string to integer", "error", err)
|
||||||
|
}
|
||||||
|
random[i] = int64(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
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate reward for reward checkpoint.
|
// Calculate reward for reward checkpoint.
|
||||||
func GetRewardForCheckpoint(chain consensus.ChainReader, blockSignerAddr common.Address, number uint64, rCheckpoint uint64, client bind.ContractBackend, totalSigner *uint64) (map[common.Address]*rewardLog, error) {
|
func GetRewardForCheckpoint(chain consensus.ChainReader, blockSignerAddr common.Address, number uint64, rCheckpoint uint64, client bind.ContractBackend, totalSigner *uint64) (map[common.Address]*rewardLog, error) {
|
||||||
// Not reward for singer of genesis block and only calculate reward at checkpoint block.
|
// Not reward for singer of genesis block and only calculate reward at checkpoint block.
|
||||||
|
|
@ -250,3 +485,154 @@ func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common
|
||||||
|
|
||||||
return balances, nil
|
return balances, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dynamic generate array sequence of numbers.
|
||||||
|
func NewSlice(start int64, end int64, step int64) []int64 {
|
||||||
|
s := make([]int64, end-start)
|
||||||
|
for i := range s {
|
||||||
|
s[i] = start
|
||||||
|
start += step
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle array.
|
||||||
|
func Shuffle(slice []int64) []int64 {
|
||||||
|
newSlice := make([]int64, len(slice))
|
||||||
|
copy(newSlice, slice)
|
||||||
|
|
||||||
|
for i := 0; i < len(slice)-1; i++ {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
randIndex := rand.Intn(len(newSlice))
|
||||||
|
x := newSlice[i]
|
||||||
|
newSlice[i] = newSlice[randIndex]
|
||||||
|
newSlice[randIndex] = x
|
||||||
|
}
|
||||||
|
|
||||||
|
return newSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// encrypt string to base64 crypto using AES
|
||||||
|
func Encrypt(key []byte, text string) string {
|
||||||
|
// key := []byte(keyText)
|
||||||
|
plaintext := []byte(text)
|
||||||
|
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The IV needs to be unique, but not secure. Therefore it's common to
|
||||||
|
// include it at the beginning of the ciphertext.
|
||||||
|
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
|
||||||
|
iv := ciphertext[:aes.BlockSize]
|
||||||
|
if _, err := io.ReadFull(cryptoRand.Reader, iv); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stream := cipher.NewCFBEncrypter(block, iv)
|
||||||
|
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
|
||||||
|
|
||||||
|
// convert to base64
|
||||||
|
return base64.URLEncoding.EncodeToString(ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrypt from base64 to decrypted string
|
||||||
|
func Decrypt(key []byte, cryptoText string) string {
|
||||||
|
ciphertext, _ := base64.URLEncoding.DecodeString(cryptoText)
|
||||||
|
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The IV needs to be unique, but not secure. Therefore it's common to
|
||||||
|
// include it at the beginning of the ciphertext.
|
||||||
|
if len(ciphertext) < aes.BlockSize {
|
||||||
|
panic("ciphertext too short")
|
||||||
|
}
|
||||||
|
iv := ciphertext[:aes.BlockSize]
|
||||||
|
ciphertext = ciphertext[aes.BlockSize:]
|
||||||
|
|
||||||
|
stream := cipher.NewCFBDecrypter(block, iv)
|
||||||
|
|
||||||
|
// XORKeyStream can work in-place if the two arguments are the same.
|
||||||
|
stream.XORKeyStream(ciphertext, ciphertext)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s", ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate random string.
|
||||||
|
func RandStringByte(n int) []byte {
|
||||||
|
letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
|
||||||
|
b := make([]byte, n)
|
||||||
|
for i := range b {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
b[i] = letterBytes[rand.Intn(len(letterBytes))]
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function check string is numeric.
|
||||||
|
func isInt(strNumber string) bool {
|
||||||
|
if _, err := strconv.Atoi(strNumber); err == nil {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
for i := 0; i < len(masternodes); i++ {
|
||||||
|
copy(masternodes[i][:], checkpointHeader.Extra[extraVanity+i*common.AddressLength:])
|
||||||
|
}
|
||||||
|
return masternodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get m2 list from checkpoint block.
|
||||||
|
func GetM2FromCheckpointBlock(checkpointBlock types.Block, ) ([]common.Address, error) {
|
||||||
|
if checkpointBlock.Number().Int64()%EpocBlockRandomize != 0 {
|
||||||
|
return nil, errors.New("This block is not checkpoint block epoc.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get singers from this block.
|
||||||
|
masternodes := GetMasternodesFromCheckpointHeader(checkpointBlock.Header())
|
||||||
|
validators := ExtractValidatorsFromBytes(checkpointBlock.Header().Validators)
|
||||||
|
|
||||||
|
var m2List []common.Address
|
||||||
|
for validatorIndex := range validators {
|
||||||
|
m2List = append(m2List, masternodes[validatorIndex])
|
||||||
|
}
|
||||||
|
|
||||||
|
return m2List, nil
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
package contracts
|
package contracts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
|
|
@ -31,22 +32,30 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSendTxSign(t *testing.T) {
|
var (
|
||||||
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||||
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
||||||
acc3Key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
acc3Key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
acc4Key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee04aefe388d1e14474d32c45c72ce7b7a")
|
acc4Key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee04aefe388d1e14474d32c45c72ce7b7a")
|
||||||
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
|
acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey)
|
||||||
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
|
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey)
|
||||||
acc3Addr := crypto.PubkeyToAddress(acc3Key.PublicKey)
|
acc3Addr = crypto.PubkeyToAddress(acc3Key.PublicKey)
|
||||||
acc4Addr := crypto.PubkeyToAddress(acc4Key.PublicKey)
|
acc4Addr = crypto.PubkeyToAddress(acc4Key.PublicKey)
|
||||||
accounts := []common.Address{acc2Addr, acc3Addr, acc4Addr}
|
)
|
||||||
keys := []*ecdsa.PrivateKey{acc2Key, acc3Key, acc4Key}
|
|
||||||
|
|
||||||
signer := types.HomesteadSigner{}
|
func getCommonBackend() *backends.SimulatedBackend {
|
||||||
genesis := core.GenesisAlloc{acc1Addr: {Balance: big.NewInt(1000000000)}}
|
genesis := core.GenesisAlloc{acc1Addr: {Balance: big.NewInt(1000000000000)}}
|
||||||
backend := backends.NewSimulatedBackend(genesis)
|
backend := backends.NewSimulatedBackend(genesis)
|
||||||
backend.Commit()
|
backend.Commit()
|
||||||
|
|
||||||
|
return backend
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendTxSign(t *testing.T) {
|
||||||
|
accounts := []common.Address{acc2Addr, acc3Addr, acc4Addr}
|
||||||
|
keys := []*ecdsa.PrivateKey{acc2Key, acc3Key, acc4Key}
|
||||||
|
backend := getCommonBackend()
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
transactOpts := bind.NewKeyedTransactor(acc1Key)
|
transactOpts := bind.NewKeyedTransactor(acc1Key)
|
||||||
|
|
@ -115,3 +124,118 @@ func randomHash() common.Hash {
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unit test for get random position of masternodes.
|
||||||
|
func TestRandomMasterNode(t *testing.T) {
|
||||||
|
oldSlice := NewSlice(0, 10, 1)
|
||||||
|
newSlice := Shuffle(oldSlice)
|
||||||
|
for _, newNumber := range newSlice {
|
||||||
|
for i, oldNumber := range oldSlice {
|
||||||
|
if oldNumber == newNumber {
|
||||||
|
// Delete find element.
|
||||||
|
oldSlice = append(oldSlice[:i], oldSlice[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(oldSlice) != 0 {
|
||||||
|
t.Errorf("Test generate random masternode fail %v - %v", oldSlice, newSlice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncryptDecrypt(t *testing.T) {
|
||||||
|
//byteInteger := common.LeftPadBytes([]byte(new(big.Int).SetInt64(4).String()), 32)
|
||||||
|
randomByte := RandStringByte(32)
|
||||||
|
encrypt := Encrypt(randomByte, new(big.Int).SetInt64(4).String())
|
||||||
|
decrypt := Decrypt(randomByte, encrypt)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
for i, vs := range a {
|
||||||
|
for j, v := range vs {
|
||||||
|
if v != b[i][j] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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},
|
||||||
|
}
|
||||||
|
b, err := GenM2FromRandomize(a)
|
||||||
|
t.Log("randomize", 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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}
|
||||||
|
b := BuildValidatorFromM2(a)
|
||||||
|
c := ExtractValidatorsFromBytes(b)
|
||||||
|
if !isArrayEqual([][]int64{a}, [][]int64{c}) {
|
||||||
|
t.Errorf("Fail to get m2 result %v", b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unit test for decode validator string data.
|
||||||
|
func TestDecodeValidatorsHexData(t *testing.T) {
|
||||||
|
a := "0x000000310000003000000032000000310000003000000032000000310000003000000032000000310000003000000031000000320000003000000031000000320000003000000031000000320000003000000030000000310000003200000030000000310000003200000030000000310000003200000030000000300000003100000032000000300000003100000032000000300000003100000032000000300000003200000030000000310000003200000030000000310000003200000030000000310000003000000030"
|
||||||
|
b, err := DecodeValidatorsHexData(a)
|
||||||
|
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}) {
|
||||||
|
t.Errorf("Fail to get m2 result %v", b)
|
||||||
|
}
|
||||||
|
t.Log("b", b)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,8 @@ func (l *txList) Overlaps(tx *types.Transaction) bool {
|
||||||
func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
|
func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
|
||||||
// If there's an older better transaction, abort
|
// If there's an older better transaction, abort
|
||||||
old := l.txs.Get(tx.Nonce())
|
old := l.txs.Get(tx.Nonce())
|
||||||
|
|
||||||
|
if (tx.To() != nil && tx.To().String() != common.RandomizeSMC) || tx.To() == nil {
|
||||||
if old != nil {
|
if old != nil {
|
||||||
threshold := new(big.Int).Div(new(big.Int).Mul(old.GasPrice(), big.NewInt(100+int64(priceBump))), big.NewInt(100))
|
threshold := new(big.Int).Div(new(big.Int).Mul(old.GasPrice(), big.NewInt(100+int64(priceBump))), big.NewInt(100))
|
||||||
// Have to ensure that the new gas price is higher than the old gas
|
// Have to ensure that the new gas price is higher than the old gas
|
||||||
|
|
@ -260,6 +262,8 @@ func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Tran
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise overwrite the old transaction with the current one
|
// Otherwise overwrite the old transaction with the current one
|
||||||
l.txs.Put(tx)
|
l.txs.Put(tx)
|
||||||
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
|
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
|
||||||
|
|
|
||||||
|
|
@ -589,7 +589,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
return ErrInsufficientFunds
|
return ErrInsufficientFunds
|
||||||
}
|
}
|
||||||
|
|
||||||
if tx.To() == nil || (tx.To() != nil && tx.To().String() != common.BlockSigners) {
|
if tx.To() != nil && tx.To().String() != common.BlockSigners && tx.To().String() != common.RandomizeSMC {
|
||||||
intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
|
intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ type Header struct {
|
||||||
Extra []byte `json:"extraData" gencodec:"required"`
|
Extra []byte `json:"extraData" gencodec:"required"`
|
||||||
MixDigest common.Hash `json:"mixHash" gencodec:"required"`
|
MixDigest common.Hash `json:"mixHash" gencodec:"required"`
|
||||||
Nonce BlockNonce `json:"nonce" gencodec:"required"`
|
Nonce BlockNonce `json:"nonce" gencodec:"required"`
|
||||||
|
Validators []byte `json:"validators" gencodec:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// field type overrides for gencodec
|
// field type overrides for gencodec
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, authorized := snap.Signers[eth.etherbase]; authorized {
|
if _, authorized := snap.Signers[eth.etherbase]; authorized {
|
||||||
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block); err != nil {
|
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
|
||||||
log.Error("Fail to create tx sign for imported block", "error", err)
|
log.Error("Fail to create tx sign for imported block", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -251,6 +251,42 @@ 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
|
||||||
|
// Get signers from snapshot.
|
||||||
|
snap, err := c.GetSnapshot(eth.blockchain, chain.CurrentHeader())
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to get snapshot for get secret and opening.", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
signers := snap.Signers
|
||||||
|
|
||||||
|
if len(signers) > 0 {
|
||||||
|
for addr := range signers {
|
||||||
|
random, err := contracts.GetRandomizeFromContract(client, addr)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Fail to get random m2 from contract.", "error", err)
|
||||||
|
}
|
||||||
|
if random != nil {
|
||||||
|
candidates = append(candidates, random)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get randomize m2 list.
|
||||||
|
m2, err := contracts.GenM2FromRandomize(candidates)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Can not get m2 from randomize SC", "error", err)
|
||||||
|
}
|
||||||
|
if len(m2) > 0 {
|
||||||
|
header.Validators = contracts.BuildValidatorFromM2(m2)
|
||||||
|
}
|
||||||
|
log.Debug("list m2", "M2", m2)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -816,6 +816,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
|
||||||
"timestamp": (*hexutil.Big)(head.Time),
|
"timestamp": (*hexutil.Big)(head.Time),
|
||||||
"transactionsRoot": head.TxHash,
|
"transactionsRoot": head.TxHash,
|
||||||
"receiptsRoot": head.ReceiptHash,
|
"receiptsRoot": head.ReceiptHash,
|
||||||
|
"validators": hexutil.Bytes(head.Validators),
|
||||||
}
|
}
|
||||||
|
|
||||||
if inclTx {
|
if inclTx {
|
||||||
|
|
|
||||||
|
|
@ -365,7 +365,7 @@ func (self *worker) wait() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Send tx sign to smart contract blockSigners.
|
// Send tx sign to smart contract blockSigners.
|
||||||
if err := contracts.CreateTransactionSign(self.config, self.eth.TxPool(), self.eth.AccountManager(), block); err != nil {
|
if err := contracts.CreateTransactionSign(self.config, self.eth.TxPool(), self.eth.AccountManager(), block, self.chainDb); err != nil {
|
||||||
log.Error("Fail to create tx sign for signer", "error", "err")
|
log.Error("Fail to create tx sign for signer", "error", "err")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue