parent
26efc233d7
commit
f77508ae84
@ -1,36 +0,0 @@ |
|||||||
package node |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
|
|
||||||
"github.com/harmony-one/harmony/crypto/bls" |
|
||||||
|
|
||||||
"github.com/harmony-one/harmony/consensus" |
|
||||||
"github.com/harmony-one/harmony/internal/utils" |
|
||||||
"github.com/harmony-one/harmony/p2p" |
|
||||||
"github.com/harmony-one/harmony/p2p/p2pimpl" |
|
||||||
) |
|
||||||
|
|
||||||
func prepareNode(t *testing.T) *Node { |
|
||||||
pubKey := bls.RandPrivateKey().GetPublicKey() |
|
||||||
leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", ConsensusPubKey: pubKey} |
|
||||||
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") |
|
||||||
host, err := p2pimpl.NewHost(&leader, priKey) |
|
||||||
if err != nil { |
|
||||||
t.Fatalf("newhost failure: %v", err) |
|
||||||
} |
|
||||||
consensus, err := consensus.New(host, 0, leader, nil) |
|
||||||
if err != nil { |
|
||||||
t.Fatalf("Cannot craeate consensus: %v", err) |
|
||||||
} |
|
||||||
return New(host, consensus, testDBFactory, false) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
func TestAddLotteryContract(t *testing.T) { |
|
||||||
node := prepareNode(t) |
|
||||||
node.AddLotteryContract() |
|
||||||
if len(node.DemoContractAddress) == 0 { |
|
||||||
t.Error("Can not create demo contract") |
|
||||||
} |
|
||||||
} |
|
@ -1,215 +0,0 @@ |
|||||||
package node |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"math" |
|
||||||
"math/big" |
|
||||||
"os" |
|
||||||
"strings" |
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi" |
|
||||||
"github.com/ethereum/go-ethereum/common" |
|
||||||
"github.com/ethereum/go-ethereum/crypto" |
|
||||||
"github.com/ethereum/go-ethereum/params" |
|
||||||
"github.com/harmony-one/harmony/contracts" |
|
||||||
"github.com/harmony-one/harmony/core/types" |
|
||||||
"github.com/harmony-one/harmony/internal/utils" |
|
||||||
contract_constants "github.com/harmony-one/harmony/internal/utils/contract" |
|
||||||
) |
|
||||||
|
|
||||||
// Constants for lottery.
|
|
||||||
const ( |
|
||||||
Enter = "enter" |
|
||||||
PickWinner = "pickWinner" |
|
||||||
GetPlayers = "getPlayers" |
|
||||||
PuzzleFund = 100000000 |
|
||||||
) |
|
||||||
|
|
||||||
// AddLotteryContract adds the demo lottery contract the genesis block.
|
|
||||||
func (node *Node) AddLotteryContract() { |
|
||||||
// Add a lottery demo contract.
|
|
||||||
priKey, err := crypto.HexToECDSA(contract_constants.DemoAccounts[0].Private) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Error when creating private key for demo contract") |
|
||||||
// Exit here to recognize the coding working.
|
|
||||||
// Basically we will remove this logic when launching so it's fine for now.
|
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
dataEnc := common.FromHex(contracts.LotteryBin) |
|
||||||
// Unsigned transaction to avoid the case of transaction address.
|
|
||||||
|
|
||||||
contractFunds := big.NewInt(0) |
|
||||||
contractFunds = contractFunds.Mul(contractFunds, big.NewInt(params.Ether)) |
|
||||||
demoContract, _ := types.SignTx( |
|
||||||
types.NewContractCreation(uint64(0), node.Consensus.ShardID, contractFunds, params.TxGasContractCreation*10, nil, dataEnc), |
|
||||||
types.HomesteadSigner{}, |
|
||||||
priKey) |
|
||||||
node.DemoContractAddress = crypto.CreateAddress(crypto.PubkeyToAddress(priKey.PublicKey), uint64(0)) |
|
||||||
node.LotteryManagerPrivateKey = priKey |
|
||||||
node.addPendingTransactions(types.Transactions{demoContract}) |
|
||||||
} |
|
||||||
|
|
||||||
// CreateTransactionForEnterMethod generates transaction for enter method and add it into pending tx list.
|
|
||||||
func (node *Node) CreateTransactionForEnterMethod(amount int64, priKey string) error { |
|
||||||
var err error |
|
||||||
toAddress := node.DemoContractAddress |
|
||||||
|
|
||||||
abi, err := abi.JSON(strings.NewReader(contracts.LotteryABI)) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) |
|
||||||
return err |
|
||||||
} |
|
||||||
bytesData, err := abi.Pack(Enter) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) |
|
||||||
return err |
|
||||||
} |
|
||||||
|
|
||||||
key, err := crypto.HexToECDSA(priKey) |
|
||||||
nonce := node.GetNonceOfAddress(crypto.PubkeyToAddress(key.PublicKey)) |
|
||||||
Amount := big.NewInt(amount) |
|
||||||
Amount = Amount.Mul(Amount, big.NewInt(params.Ether)) |
|
||||||
tx := types.NewTransaction( |
|
||||||
nonce, |
|
||||||
toAddress, |
|
||||||
node.NodeConfig.ShardID, |
|
||||||
Amount, |
|
||||||
params.TxGas*10, |
|
||||||
nil, |
|
||||||
bytesData, |
|
||||||
) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to get private key", "error", err) |
|
||||||
return err |
|
||||||
} |
|
||||||
if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key); err == nil { |
|
||||||
node.addPendingTransactions(types.Transactions{signedTx}) |
|
||||||
return nil |
|
||||||
} |
|
||||||
utils.GetLogInstance().Error("Unable to call enter method", "error", err) |
|
||||||
return err |
|
||||||
} |
|
||||||
|
|
||||||
// GetResultDirectly get current players and their balances, not from smart contract.
|
|
||||||
func (node *Node) GetResultDirectly(priKey string) (players []string, balances []*big.Int) { |
|
||||||
for _, account := range contract_constants.DemoAccounts { |
|
||||||
players = append(players, account.Private) |
|
||||||
key, err := crypto.HexToECDSA(account.Private) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Error when HexToECDSA") |
|
||||||
} |
|
||||||
address := crypto.PubkeyToAddress(key.PublicKey) |
|
||||||
balance, err := node.GetBalanceOfAddress(address) |
|
||||||
balances = append(balances, balance) |
|
||||||
} |
|
||||||
return players, balances |
|
||||||
} |
|
||||||
|
|
||||||
// GenerateResultDirectly get current players and their balances, not from smart contract.
|
|
||||||
func (node *Node) GenerateResultDirectly(addresses []common.Address) (players []string, balances []*big.Int) { |
|
||||||
for _, address := range addresses { |
|
||||||
players = append(players, address.String()) |
|
||||||
balance, _ := node.GetBalanceOfAddress(address) |
|
||||||
balances = append(balances, balance) |
|
||||||
} |
|
||||||
fmt.Println("generate result", players, balances) |
|
||||||
return players, balances |
|
||||||
} |
|
||||||
|
|
||||||
// GetResult get current players and their balances.
|
|
||||||
func (node *Node) GetResult(priKey string) (players []string, balances []*big.Int) { |
|
||||||
// TODO(minhdoan): get result from smart contract is current not working. Fix it later.
|
|
||||||
abi, err := abi.JSON(strings.NewReader(contracts.LotteryABI)) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) |
|
||||||
} |
|
||||||
bytesData, err := abi.Pack("getPlayers") |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) |
|
||||||
} |
|
||||||
|
|
||||||
demoContractAddress := node.DemoContractAddress |
|
||||||
key, err := crypto.HexToECDSA(priKey) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to parse private key", "error", err) |
|
||||||
} |
|
||||||
|
|
||||||
nonce := node.GetNonceOfAddress(crypto.PubkeyToAddress(key.PublicKey)) |
|
||||||
|
|
||||||
tx := types.NewTransaction( |
|
||||||
nonce, |
|
||||||
demoContractAddress, |
|
||||||
node.NodeConfig.ShardID, |
|
||||||
nil, |
|
||||||
math.MaxUint64, |
|
||||||
nil, |
|
||||||
bytesData, |
|
||||||
) |
|
||||||
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to sign contract call tx", "error", err) |
|
||||||
return nil, nil |
|
||||||
} |
|
||||||
output, err := node.ContractCaller.CallContract(signedTx) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to call staking contract", "error", err) |
|
||||||
return nil, nil |
|
||||||
} |
|
||||||
|
|
||||||
ret := []common.Address{} |
|
||||||
err = abi.Unpack(&ret, "getPlayers", output) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to unpack getPlayers", "error", err) |
|
||||||
return nil, nil |
|
||||||
} |
|
||||||
utils.GetLogInstance().Info("get result: ", "ret", ret) |
|
||||||
fmt.Println("get result called:", ret) |
|
||||||
return node.GenerateResultDirectly(ret) |
|
||||||
} |
|
||||||
|
|
||||||
// CreateTransactionForPickWinner generates transaction for enter method and add it into pending tx list.
|
|
||||||
func (node *Node) CreateTransactionForPickWinner() error { |
|
||||||
var err error |
|
||||||
toAddress := node.DemoContractAddress |
|
||||||
|
|
||||||
abi, err := abi.JSON(strings.NewReader(contracts.LotteryABI)) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) |
|
||||||
return err |
|
||||||
} |
|
||||||
bytesData, err := abi.Pack(PickWinner) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) |
|
||||||
return err |
|
||||||
} |
|
||||||
|
|
||||||
key := node.LotteryManagerPrivateKey |
|
||||||
if key == nil { |
|
||||||
return fmt.Errorf("LotterManagerPrivateKey is nil") |
|
||||||
} |
|
||||||
nonce := node.GetNonceOfAddress(crypto.PubkeyToAddress(key.PublicKey)) |
|
||||||
Amount := big.NewInt(0) |
|
||||||
tx := types.NewTransaction( |
|
||||||
nonce, |
|
||||||
toAddress, |
|
||||||
node.NodeConfig.ShardID, |
|
||||||
Amount, |
|
||||||
params.TxGas*1000, |
|
||||||
nil, |
|
||||||
bytesData, |
|
||||||
) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to get private key", "error", err) |
|
||||||
return err |
|
||||||
} |
|
||||||
if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key); err == nil { |
|
||||||
node.addPendingTransactions(types.Transactions{signedTx}) |
|
||||||
return nil |
|
||||||
} |
|
||||||
utils.GetLogInstance().Error("Unable to call enter method", "error", err) |
|
||||||
return err |
|
||||||
} |
|
@ -1,228 +0,0 @@ |
|||||||
package node |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"math/big" |
|
||||||
"os" |
|
||||||
"strings" |
|
||||||
"sync/atomic" |
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi" |
|
||||||
"github.com/ethereum/go-ethereum/common" |
|
||||||
"github.com/ethereum/go-ethereum/crypto" |
|
||||||
"github.com/ethereum/go-ethereum/params" |
|
||||||
"github.com/harmony-one/harmony/contracts" |
|
||||||
"github.com/harmony-one/harmony/core/types" |
|
||||||
"github.com/harmony-one/harmony/internal/utils" |
|
||||||
contract_constants "github.com/harmony-one/harmony/internal/utils/contract" |
|
||||||
) |
|
||||||
|
|
||||||
// Constants for puzzle.
|
|
||||||
const ( |
|
||||||
Play = "play" |
|
||||||
Payout = "payout" |
|
||||||
EndGame = "endGame" |
|
||||||
) |
|
||||||
|
|
||||||
// OneEther is one ether
|
|
||||||
var OneEther = big.NewInt(params.Ether) |
|
||||||
|
|
||||||
// AddPuzzleContract adds the demo puzzle contract the genesis block.
|
|
||||||
func (node *Node) AddPuzzleContract() { |
|
||||||
// Add a puzzle demo contract.
|
|
||||||
priKey, err := crypto.HexToECDSA(contract_constants.PuzzleAccounts[0].Private) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Error when creating private key for puzzle demo contract") |
|
||||||
// Exit here to recognize the coding working.
|
|
||||||
// Basically we will remove this logic when launching so it's fine for now.
|
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
dataEnc := common.FromHex(contracts.PuzzleBin) |
|
||||||
// Unsigned transaction to avoid the case of transaction address.
|
|
||||||
|
|
||||||
contractFunds := big.NewInt(PuzzleFund) |
|
||||||
contractFunds = contractFunds.Mul(contractFunds, big.NewInt(params.Ether)) |
|
||||||
demoContract, _ := types.SignTx( |
|
||||||
types.NewContractCreation(uint64(0), node.Consensus.ShardID, contractFunds, params.TxGasContractCreation*1000, nil, dataEnc), |
|
||||||
types.HomesteadSigner{}, |
|
||||||
priKey) |
|
||||||
node.PuzzleContractAddress = crypto.CreateAddress(crypto.PubkeyToAddress(priKey.PublicKey), uint64(0)) |
|
||||||
node.PuzzleManagerPrivateKey = priKey |
|
||||||
node.addPendingTransactions(types.Transactions{demoContract}) |
|
||||||
} |
|
||||||
|
|
||||||
// CreateTransactionForPlayMethod generates transaction for play method and add it into pending tx list.
|
|
||||||
func (node *Node) CreateTransactionForPlayMethod(priKey string, amount int64) (string, error) { |
|
||||||
var err error |
|
||||||
toAddress := node.PuzzleContractAddress |
|
||||||
abi, err := abi.JSON(strings.NewReader(contracts.PuzzleABI)) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("puzzle-play: Failed to generate staking contract's ABI", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
bytesData, err := abi.Pack(Play) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("puzzle-play: Failed to generate ABI function bytes data", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
|
|
||||||
Stake := big.NewInt(0) |
|
||||||
Stake = Stake.Mul(OneEther, big.NewInt(amount)) |
|
||||||
|
|
||||||
key, err := crypto.HexToECDSA(priKey) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to parse private key", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
address := crypto.PubkeyToAddress(key.PublicKey) |
|
||||||
balance, err := node.GetBalanceOfAddress(address) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("puzzle-play: can not get address", "error", err) |
|
||||||
return "", err |
|
||||||
} else if balance.Cmp(Stake) == -1 { |
|
||||||
utils.GetLogInstance().Error("puzzle-play: insufficient fund", "error", err, "stake", Stake, "balance", balance) |
|
||||||
return "", ErrPuzzleInsufficientFund |
|
||||||
} |
|
||||||
nonce := node.GetAndIncreaseAddressNonce(address) |
|
||||||
tx := types.NewTransaction( |
|
||||||
nonce, |
|
||||||
toAddress, |
|
||||||
node.NodeConfig.ShardID, |
|
||||||
Stake, |
|
||||||
params.TxGas*100, |
|
||||||
nil, |
|
||||||
bytesData, |
|
||||||
) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("puzzle-play: Failed to get private key", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key); err == nil { |
|
||||||
node.addPendingTransactions(types.Transactions{signedTx}) |
|
||||||
return signedTx.Hash().Hex(), nil |
|
||||||
} |
|
||||||
utils.GetLogInstance().Error("puzzle-play: Unable to call enter method", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
|
|
||||||
// CreateTransactionForPayoutMethod generates transaction for payout method and add it into pending tx list.
|
|
||||||
func (node *Node) CreateTransactionForPayoutMethod(priKey string, level int, sequence string) (string, error) { |
|
||||||
var err error |
|
||||||
toAddress := node.PuzzleContractAddress |
|
||||||
|
|
||||||
abi, err := abi.JSON(strings.NewReader(contracts.PuzzleABI)) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
|
|
||||||
key, err := crypto.HexToECDSA(priKey) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to parse private key", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
address := crypto.PubkeyToAddress(key.PublicKey) |
|
||||||
|
|
||||||
// add params for address payable player, uint8 new_level, steps string
|
|
||||||
fmt.Println("Payout: address", address) |
|
||||||
bytesData, err := abi.Pack(Payout, address, big.NewInt(int64(level)), sequence) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
|
|
||||||
if key == nil { |
|
||||||
return "", fmt.Errorf("user key is nil") |
|
||||||
} |
|
||||||
nonce := node.GetAndIncreaseAddressNonce(address) |
|
||||||
Amount := big.NewInt(0) |
|
||||||
tx := types.NewTransaction( |
|
||||||
nonce, |
|
||||||
toAddress, |
|
||||||
node.NodeConfig.ShardID, |
|
||||||
Amount, |
|
||||||
params.TxGas*10, |
|
||||||
nil, |
|
||||||
bytesData, |
|
||||||
) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to get private key", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key); err == nil { |
|
||||||
node.addPendingTransactions(types.Transactions{signedTx}) |
|
||||||
return signedTx.Hash().Hex(), nil |
|
||||||
} |
|
||||||
utils.GetLogInstance().Error("Unable to call enter method", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
|
|
||||||
// CreateTransactionForEndMethod generates transaction for endGame method and add it into pending tx list.
|
|
||||||
func (node *Node) CreateTransactionForEndMethod(priKey string) (string, error) { |
|
||||||
var err error |
|
||||||
toAddress := node.PuzzleContractAddress |
|
||||||
|
|
||||||
abi, err := abi.JSON(strings.NewReader(contracts.PuzzleABI)) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
key, err := crypto.HexToECDSA(priKey) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to parse private key", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
address := crypto.PubkeyToAddress(key.PublicKey) |
|
||||||
|
|
||||||
// add params for address payable player, uint8 new_level, steps string
|
|
||||||
fmt.Println("EndGame: address", address) |
|
||||||
bytesData, err := abi.Pack(EndGame, address) |
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
|
|
||||||
if key == nil { |
|
||||||
return "", fmt.Errorf("user key is nil") |
|
||||||
} |
|
||||||
nonce := node.GetAndIncreaseAddressNonce(address) |
|
||||||
Amount := big.NewInt(0) |
|
||||||
tx := types.NewTransaction( |
|
||||||
nonce, |
|
||||||
toAddress, |
|
||||||
node.NodeConfig.ShardID, |
|
||||||
Amount, |
|
||||||
params.TxGas*10, |
|
||||||
nil, |
|
||||||
bytesData, |
|
||||||
) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
utils.GetLogInstance().Error("Failed to get private key", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key); err == nil { |
|
||||||
node.addPendingTransactions(types.Transactions{signedTx}) |
|
||||||
return signedTx.Hash().Hex(), nil |
|
||||||
} |
|
||||||
utils.GetLogInstance().Error("Unable to call enter method", "error", err) |
|
||||||
return "", err |
|
||||||
} |
|
||||||
|
|
||||||
// GetAndIncreaseAddressNonce get and increase the address's nonce
|
|
||||||
func (node *Node) GetAndIncreaseAddressNonce(address common.Address) uint64 { |
|
||||||
if value, ok := node.AddressNonce.Load(address); ok { |
|
||||||
n, ok := value.(uint64) |
|
||||||
if !ok { |
|
||||||
return 0 |
|
||||||
} |
|
||||||
nonce := atomic.AddUint64(&n, 1) |
|
||||||
return nonce - 1 |
|
||||||
} |
|
||||||
nonce := node.GetNonceOfAddress(address) + 1 |
|
||||||
node.AddressNonce.Store(address, nonce) |
|
||||||
return nonce - 1 |
|
||||||
} |
|
Loading…
Reference in new issue