Merge pull request #154 from harmony-one/rj_branch

[HAR-20] Implement faucet functionality and sharded transaction for wallet
pull/156/head
Leo Chen 6 years ago committed by GitHub
commit e0276d9435
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      beaconchain/libs/beaconchain.go
  2. 9
      client/client.go
  3. 12
      client/service/client.go
  4. 131
      client/service/proto/client.pb.go
  5. 13
      client/service/proto/client.proto
  6. 13
      client/service/server.go
  7. 84
      client/wallet/main.go
  8. 8
      consensus/consensus_leader.go
  9. 5
      core/types/transaction.go
  10. 2
      deploy.sh
  11. 15
      harmony/main.go
  12. 62
      node/node.go
  13. 1
      node/node_handler.go
  14. 8
      node/worker/worker.go

@ -61,7 +61,11 @@ func (bc *BeaconChain) StartRPCServer() {
// GetShardLeaderMap returns the map from shard id to leader.
func (bc *BeaconChain) GetShardLeaderMap() map[int]*bcconn.NodeInfo {
return bc.ShardLeaderMap
result := make(map[int]*bcconn.NodeInfo)
for i, leader := range bc.Leaders {
result[i] = leader
}
return result
}
//New beaconchain initialization
@ -93,7 +97,6 @@ func (bc *BeaconChain) AcceptConnections(b []byte) {
_, isLeader := utils.AllocateShard(bc.NumberOfNodesAdded, bc.NumberOfShards)
if isLeader {
bc.Leaders = append(bc.Leaders, Node)
bc.ShardLeaderMap[bc.NumberOfNodesAdded-1] = Node
}
response := bcconn.ResponseRandomNumber{NumberOfShards: bc.NumberOfShards, NumberOfNodesAdded: bc.NumberOfNodesAdded, Leaders: bc.Leaders}
msg := bcconn.SerializeRandomInfo(response)

@ -178,3 +178,12 @@ func (client *Client) GetLeaders() []p2p.Peer {
}
return leaders
}
//// GetLeaders returns leader peers.
//func (client *Client) GetShardLeader(uint32 shardID) p2p.Peer {
// leaders := []p2p.Peer{}
// for _, leader := range *client.Leaders {
// leaders = append(leaders, leader)
// }
// return leaders
//}

@ -49,3 +49,15 @@ func (client *Client) GetBalance(address common.Address) *proto.FetchAccountStat
}
return response
}
// GetFreeToken requests free token from the faucet contract.
func (client *Client) GetFreeToken(address common.Address) *proto.GetFreeTokenResponse {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
request := &proto.GetFreeTokenRequest{Address: address.Bytes()}
response, err := client.clientServiceClient.GetFreeToken(ctx, request)
if err != nil {
log.Fatalf("Error getting free token: %s", err)
}
return response
}

@ -113,15 +113,99 @@ func (m *FetchAccountStateResponse) GetNonce() uint64 {
return 0
}
// GetFreeTokenRequest is the request to get free token from the faucet smart contract.
type GetFreeTokenRequest struct {
// The account address to receive the free token
Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetFreeTokenRequest) Reset() { *m = GetFreeTokenRequest{} }
func (m *GetFreeTokenRequest) String() string { return proto.CompactTextString(m) }
func (*GetFreeTokenRequest) ProtoMessage() {}
func (*GetFreeTokenRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_014de31d7ac8c57c, []int{2}
}
func (m *GetFreeTokenRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetFreeTokenRequest.Unmarshal(m, b)
}
func (m *GetFreeTokenRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetFreeTokenRequest.Marshal(b, m, deterministic)
}
func (m *GetFreeTokenRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetFreeTokenRequest.Merge(m, src)
}
func (m *GetFreeTokenRequest) XXX_Size() int {
return xxx_messageInfo_GetFreeTokenRequest.Size(m)
}
func (m *GetFreeTokenRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetFreeTokenRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetFreeTokenRequest proto.InternalMessageInfo
func (m *GetFreeTokenRequest) GetAddress() []byte {
if m != nil {
return m.Address
}
return nil
}
// GetFreeTokenResponse is the response of GetFreeTokenRequest.
type GetFreeTokenResponse struct {
// The transaction Id that requests free token from the faucet.
TxId []byte `protobuf:"bytes,1,opt,name=txId,proto3" json:"txId,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetFreeTokenResponse) Reset() { *m = GetFreeTokenResponse{} }
func (m *GetFreeTokenResponse) String() string { return proto.CompactTextString(m) }
func (*GetFreeTokenResponse) ProtoMessage() {}
func (*GetFreeTokenResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_014de31d7ac8c57c, []int{3}
}
func (m *GetFreeTokenResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetFreeTokenResponse.Unmarshal(m, b)
}
func (m *GetFreeTokenResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetFreeTokenResponse.Marshal(b, m, deterministic)
}
func (m *GetFreeTokenResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetFreeTokenResponse.Merge(m, src)
}
func (m *GetFreeTokenResponse) XXX_Size() int {
return xxx_messageInfo_GetFreeTokenResponse.Size(m)
}
func (m *GetFreeTokenResponse) XXX_DiscardUnknown() {
xxx_messageInfo_GetFreeTokenResponse.DiscardUnknown(m)
}
var xxx_messageInfo_GetFreeTokenResponse proto.InternalMessageInfo
func (m *GetFreeTokenResponse) GetTxId() []byte {
if m != nil {
return m.TxId
}
return nil
}
func init() {
proto.RegisterType((*FetchAccountStateRequest)(nil), "client.FetchAccountStateRequest")
proto.RegisterType((*FetchAccountStateResponse)(nil), "client.FetchAccountStateResponse")
proto.RegisterType((*GetFreeTokenRequest)(nil), "client.GetFreeTokenRequest")
proto.RegisterType((*GetFreeTokenResponse)(nil), "client.GetFreeTokenResponse")
}
func init() { proto.RegisterFile("client.proto", fileDescriptor_014de31d7ac8c57c) }
var fileDescriptor_014de31d7ac8c57c = []byte{
// 172 bytes of a gzipped FileDescriptorProto
// 229 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0xce, 0xc9, 0x4c,
0xcd, 0x2b, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xf0, 0x94, 0x4c, 0xb8, 0x24,
0xdc, 0x52, 0x4b, 0x92, 0x33, 0x1c, 0x93, 0x93, 0xf3, 0x4b, 0xf3, 0x4a, 0x82, 0x4b, 0x12, 0x4b,
@ -129,10 +213,14 @@ var fileDescriptor_014de31d7ac8c57c = []byte{
0x52, 0x8b, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x60, 0x5c, 0x25, 0x6f, 0x2e, 0x49,
0x2c, 0xba, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x41, 0xda, 0x92, 0x12, 0x73, 0x12, 0xf3, 0x92,
0x53, 0x61, 0xda, 0xa0, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0x7c, 0x90, 0x38, 0x93, 0x02, 0xa3,
0x06, 0x4b, 0x10, 0x84, 0x63, 0x94, 0xcd, 0xc5, 0xeb, 0x0c, 0x76, 0x4c, 0x70, 0x6a, 0x51, 0x59,
0x66, 0x72, 0xaa, 0x50, 0x14, 0x97, 0x20, 0x86, 0xe9, 0x42, 0x0a, 0x7a, 0x50, 0xf7, 0xe3, 0x72,
0xae, 0x94, 0x22, 0x1e, 0x15, 0x10, 0xa7, 0x29, 0x31, 0x24, 0xb1, 0x81, 0xbd, 0x6f, 0x0c, 0x08,
0x00, 0x00, 0xff, 0xff, 0x2a, 0x07, 0xa9, 0xb6, 0x0e, 0x01, 0x00, 0x00,
0x06, 0x4b, 0x10, 0x84, 0xa3, 0xa4, 0xcf, 0x25, 0xec, 0x9e, 0x5a, 0xe2, 0x56, 0x94, 0x9a, 0x1a,
0x92, 0x9f, 0x9d, 0x9a, 0x47, 0xd8, 0x76, 0x2d, 0x2e, 0x11, 0x54, 0x0d, 0x50, 0x8b, 0x85, 0xb8,
0x58, 0x4a, 0x2a, 0x3c, 0x53, 0xa0, 0xca, 0xc1, 0x6c, 0xa3, 0x1d, 0x8c, 0x5c, 0xbc, 0xce, 0x60,
0xaf, 0x06, 0xa7, 0x16, 0x95, 0x65, 0x26, 0xa7, 0x0a, 0x45, 0x71, 0x09, 0x62, 0xb8, 0x5d, 0x48,
0x41, 0x0f, 0x1a, 0x3a, 0xb8, 0x02, 0x43, 0x4a, 0x11, 0x8f, 0x0a, 0x88, 0xfd, 0x4a, 0x0c, 0x42,
0xde, 0x5c, 0x3c, 0xc8, 0x2e, 0x13, 0x92, 0x86, 0x69, 0xc2, 0xe2, 0x41, 0x29, 0x19, 0xec, 0x92,
0x30, 0xc3, 0x92, 0xd8, 0xc0, 0x31, 0x65, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc6, 0xd9, 0x35,
0x0c, 0xb9, 0x01, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -148,6 +236,7 @@ const _ = grpc.SupportPackageIsVersion4
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ClientServiceClient interface {
FetchAccountState(ctx context.Context, in *FetchAccountStateRequest, opts ...grpc.CallOption) (*FetchAccountStateResponse, error)
GetFreeToken(ctx context.Context, in *GetFreeTokenRequest, opts ...grpc.CallOption) (*GetFreeTokenResponse, error)
}
type clientServiceClient struct {
@ -167,9 +256,19 @@ func (c *clientServiceClient) FetchAccountState(ctx context.Context, in *FetchAc
return out, nil
}
func (c *clientServiceClient) GetFreeToken(ctx context.Context, in *GetFreeTokenRequest, opts ...grpc.CallOption) (*GetFreeTokenResponse, error) {
out := new(GetFreeTokenResponse)
err := c.cc.Invoke(ctx, "/client.ClientService/GetFreeToken", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ClientServiceServer is the server API for ClientService service.
type ClientServiceServer interface {
FetchAccountState(context.Context, *FetchAccountStateRequest) (*FetchAccountStateResponse, error)
GetFreeToken(context.Context, *GetFreeTokenRequest) (*GetFreeTokenResponse, error)
}
func RegisterClientServiceServer(s *grpc.Server, srv ClientServiceServer) {
@ -194,6 +293,24 @@ func _ClientService_FetchAccountState_Handler(srv interface{}, ctx context.Conte
return interceptor(ctx, in, info, handler)
}
func _ClientService_GetFreeToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetFreeTokenRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientServiceServer).GetFreeToken(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/client.ClientService/GetFreeToken",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientServiceServer).GetFreeToken(ctx, req.(*GetFreeTokenRequest))
}
return interceptor(ctx, in, info, handler)
}
var _ClientService_serviceDesc = grpc.ServiceDesc{
ServiceName: "client.ClientService",
HandlerType: (*ClientServiceServer)(nil),
@ -202,6 +319,10 @@ var _ClientService_serviceDesc = grpc.ServiceDesc{
MethodName: "FetchAccountState",
Handler: _ClientService_FetchAccountState_Handler,
},
{
MethodName: "GetFreeToken",
Handler: _ClientService_GetFreeToken_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "client.proto",

@ -5,6 +5,7 @@ package client;
// Client is the service used for any client-facing requests.
service ClientService {
rpc FetchAccountState(FetchAccountStateRequest) returns (FetchAccountStateResponse) {}
rpc GetFreeToken(GetFreeTokenRequest) returns (GetFreeTokenResponse) {}
}
// FetchAccountStateRequest is the request to fetch an account's balance and nonce.
@ -20,3 +21,15 @@ message FetchAccountStateResponse {
// The nonce of the account
uint64 nonce = 2;
}
// GetFreeTokenRequest is the request to get free token from the faucet smart contract.
message GetFreeTokenRequest {
// The account address to receive the free token
bytes address = 1;
}
// GetFreeTokenResponse is the response of GetFreeTokenRequest.
message GetFreeTokenResponse {
// The transaction Id that requests free token from the faucet.
bytes txId = 1;
}

@ -15,6 +15,7 @@ import (
// Server is the Server struct for client service package.
type Server struct {
stateReader func() (*state.StateDB, error)
callFaucetContract func(common.Address) common.Hash
}
// FetchAccountState implements the FetchAccountState interface to return account state.
@ -29,6 +30,14 @@ func (s *Server) FetchAccountState(ctx context.Context, request *proto.FetchAcco
return &proto.FetchAccountStateResponse{Balance: state.GetBalance(address).Bytes(), Nonce: state.GetNonce(address)}, nil
}
// GetFreeToken implements the GetFreeToken interface to request free token.
func (s *Server) GetFreeToken(ctx context.Context, request *proto.GetFreeTokenRequest) (*proto.GetFreeTokenResponse, error) {
var address common.Address
address.SetBytes(request.Address)
log.Println("Returning GetFreeTokenResponse for address: ", address.Hex())
return &proto.GetFreeTokenResponse{TxId: s.callFaucetContract(address).Bytes()}, nil
}
// Start starts the Server on given ip and port.
func (s *Server) Start(ip, port string) (*grpc.Server, error) {
// TODO(minhdoan): Currently not using ip. Fix it later.
@ -45,7 +54,7 @@ func (s *Server) Start(ip, port string) (*grpc.Server, error) {
}
// NewServer creates new Server which implements ClientServiceServer interface.
func NewServer(stateReader func() (*state.StateDB, error)) *Server {
s := &Server{stateReader}
func NewServer(stateReader func() (*state.StateDB, error), callFaucetContract func(common.Address) common.Hash) *Server {
s := &Server{stateReader: stateReader, callFaucetContract: callFaucetContract}
return s
}

@ -47,6 +47,13 @@ func main() {
transferSenderPtr := transferCommand.String("from", "0", "Specify the sender account address or index")
transferReceiverPtr := transferCommand.String("to", "", "Specify the receiver account")
transferAmountPtr := transferCommand.Float64("amount", 0, "Specify the amount to transfer")
transferShardIDPtr := transferCommand.Int("shardID", -1, "Specify the shard ID for the transfer")
freeTokenCommand := flag.NewFlagSet("getFreeToken", flag.ExitOnError)
freeTokenAddressPtr := freeTokenCommand.String("address", "", "Specify the account address to receive the free token")
balanceCommand := flag.NewFlagSet("getFreeToken", flag.ExitOnError)
balanceAddressPtr := balanceCommand.String("address", "", "Specify the account address to check balance for")
// Verify that a subcommand has been provided
// os.Arg[0] is the main command
@ -60,11 +67,15 @@ func main() {
fmt.Println(" 3. removeAll - Removes all accounts in local keystore")
fmt.Println(" 4. import - Imports a new account by private key")
fmt.Println(" --privateKey - the private key to import")
fmt.Println(" 5. balances - Shows the balances of all accounts")
fmt.Println(" 6. transfer")
fmt.Println(" 5. balances - Shows the balances of all addresses or specific address")
fmt.Println(" --address - The address to check balance for")
fmt.Println(" 6. getFreeToken - Gets free token on each shard")
fmt.Println(" --address - The free token receiver account's address")
fmt.Println(" 7. transfer")
fmt.Println(" --from - The sender account's address or index in the local keystore")
fmt.Println(" --to - The receiver account's address")
fmt.Println(" --amount - The amount of token to transfer")
fmt.Println(" --shardId - The shard Id for the transfer")
os.Exit(1)
}
@ -86,14 +97,15 @@ func main() {
fmt.Printf("New account created with address:\n {%s}\n", crypto2.PubkeyToAddress(priKey.PublicKey).Hex())
fmt.Printf("Please keep a copy of the private key:\n {%s}\n", hex.EncodeToString(crypto2.FromECDSA(priKey)))
case "list":
for i, address := range ReadAddresses() {
fmt.Printf("Account %d:\n {%s}\n", i, address.Hex())
for i, key := range ReadPrivateKeys() {
fmt.Printf("Account %d:\n {%s}\n", i, crypto2.PubkeyToAddress(key.PublicKey).Hex())
fmt.Printf(" PrivateKey: {%s}\n", hex.EncodeToString(key.D.Bytes()))
}
case "removeAll":
ClearKeystore()
fmt.Println("All existing accounts deleted...")
case "import":
accountImportCommand.Parse(os.Args[3:])
accountImportCommand.Parse(os.Args[2:])
priKey := *accountImportPtr
if priKey == "" {
fmt.Println("Error: --privateKey is required")
@ -109,14 +121,37 @@ func main() {
StorePrivateKey(priKeyBytes)
fmt.Println("Private key imported...")
case "balances":
balanceCommand.Parse(os.Args[2:])
walletNode := CreateWalletNode()
if *balanceAddressPtr == "" {
for i, address := range ReadAddresses() {
fmt.Printf("Account %d: %s:\n", i, address.Hex())
for shardID, balanceNonce := range FetchBalance(address, walletNode) {
fmt.Printf(" Balance in Shard %d: %.6f \n", shardID, float32(balanceNonce.balance.Uint64())/params.Ether)
balance := balanceNonce.balance
balance = balance.Div(balance, big.NewInt(params.GWei))
fmt.Printf(" Balance in Shard %d: %.6f \n", shardID, float32(balanceNonce.balance.Uint64())/params.GWei)
}
}
} else {
address := common.HexToAddress(*freeTokenAddressPtr)
for shardID, balanceNonce := range FetchBalance(address, walletNode) {
balance := balanceNonce.balance
balance = balance.Div(balance, big.NewInt(params.GWei))
fmt.Printf(" Balance in Shard %d: %.6f \n", shardID, float32(balanceNonce.balance.Uint64())/params.GWei)
}
}
case "getFreeToken":
freeTokenCommand.Parse(os.Args[2:])
walletNode := CreateWalletNode()
if *freeTokenAddressPtr == "" {
fmt.Println("Error: --address is required")
return
}
address := common.HexToAddress(*freeTokenAddressPtr)
GetFreeToken(address, walletNode)
case "transfer":
transferCommand.Parse(os.Args[2:])
if !transferCommand.Parsed() {
@ -125,9 +160,15 @@ func main() {
sender := *transferSenderPtr
receiver := *transferReceiverPtr
amount := *transferAmountPtr
shardID := *transferShardIDPtr
if shardID == -1 {
fmt.Println("Please specify the shard ID for the transfer (e.g. --shardID=0)")
return
}
if amount <= 0 {
fmt.Println("Please specify positive amount to transfer")
return
}
priKeys := ReadPrivateKeys()
if len(priKeys) == 0 {
@ -167,14 +208,19 @@ func main() {
walletNode := CreateWalletNode()
shardIDToAccountState := FetchBalance(senderAddress, walletNode)
if float64(shardIDToAccountState[0].balance.Uint64())/params.Ether < amount {
fmt.Printf("Balance is not enough for the transfer, current balance is %.6f\n", float64(shardIDToAccountState[0].balance.Uint64())/params.Ether)
balance := shardIDToAccountState[uint32(shardID)].balance
balance = balance.Div(balance, big.NewInt(params.GWei))
if amount > float64(balance.Uint64())/params.GWei {
fmt.Printf("Balance is not enough for the transfer, current balance is %.6f\n", float64(balance.Uint64())/params.GWei)
return
}
fmt.Println(big.NewInt(int64(amount * params.Ether)))
tx, _ := types.SignTx(types.NewTransaction(shardIDToAccountState[0].nonce, receiverAddress, 0, big.NewInt(int64(amount*params.Ether)), params.TxGas, nil, nil), types.HomesteadSigner{}, senderPriKey)
SubmitTransaction(tx, walletNode)
amountBigInt := big.NewInt(int64(amount * params.GWei))
amountBigInt = amountBigInt.Mul(amountBigInt, big.NewInt(params.GWei))
tx, _ := types.SignTx(types.NewTransaction(shardIDToAccountState[uint32(shardID)].nonce, receiverAddress, uint32(shardID), amountBigInt, params.TxGas, nil, nil), types.HomesteadSigner{}, senderPriKey)
SubmitTransaction(tx, walletNode, uint32(shardID))
default:
fmt.Printf("Unknown action: %s\n", os.Args[1])
flag.PrintDefaults()
os.Exit(1)
}
@ -222,9 +268,11 @@ func CreateWalletNode() *node.Node {
}
// SubmitTransaction submits the transaction to the Harmony network
func SubmitTransaction(tx *types.Transaction, walletNode *node.Node) error {
func SubmitTransaction(tx *types.Transaction, walletNode *node.Node, shardID uint32) error {
msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx})
walletNode.BroadcastMessage(walletNode.Client.GetLeaders(), msg)
leader := (*walletNode.Client.Leaders)[shardID]
walletNode.SendMessage(leader, msg)
fmt.Printf("Transaction Id for shard %d: %s\n", int(shardID), common.BytesToAddress(tx.Hash().Bytes()).Hex())
time.Sleep(300 * time.Millisecond)
return nil
}
@ -244,6 +292,16 @@ func FetchBalance(address common.Address, walletNode *node.Node) map[uint32]Acco
return result
}
// GetFreeToken requests for token test token on each shard
func GetFreeToken(address common.Address, walletNode *node.Node) {
for shardID, leader := range *walletNode.Client.Leaders {
port, _ := strconv.Atoi(leader.Port)
client := client2.NewClient(leader.IP, strconv.Itoa(port+node.ClientServicePortDiff))
response := client.GetFreeToken(address)
fmt.Printf("Transaction Id requesting free token in shard %d: %s\n", int(shardID), common.BytesToAddress(response.TxId).Hex())
}
}
// FetchUtxos fetches utxos of specified address from the Harmony network
func FetchUtxos(addresses [][20]byte, walletNode *node.Node) (map[uint32]blockchain.UtxoMap, error) {
walletNode.Client.ShardUtxoMap = make(map[uint32]blockchain.UtxoMap)

@ -25,7 +25,7 @@ import (
)
const (
waitForEnoughValidators = 300
waitForEnoughValidators = 1000
)
var (
@ -43,10 +43,9 @@ func (consensus *Consensus) WaitForNewBlock(blockChannel chan blockchain.Block)
consensus.Log.Debug("WaitForNewBlock", "removed peers", c)
}
if !consensus.HasEnoughValidators() {
for !consensus.HasEnoughValidators() {
consensus.Log.Debug("Not enough validators", "# Validators", len(consensus.PublicKeys))
time.Sleep(waitForEnoughValidators * time.Millisecond)
continue
}
// TODO: think about potential race condition
@ -73,10 +72,9 @@ func (consensus *Consensus) WaitForNewBlockAccount(blockChannel chan *types.Bloc
consensus.Log.Debug("WaitForNewBlock", "removed peers", c)
}
if !consensus.HasEnoughValidators() {
for !consensus.HasEnoughValidators() {
consensus.Log.Debug("Not enough validators", "# Validators", len(consensus.PublicKeys))
time.Sleep(waitForEnoughValidators * time.Millisecond)
continue
}
startTime = time.Now()

@ -115,6 +115,11 @@ func (tx *Transaction) ChainID() *big.Int {
return deriveChainID(tx.data.V)
}
// ShardID returns which shard id this transaction was signed for (if at all)
func (tx *Transaction) ShardID() uint32 {
return tx.data.ShardID
}
// Protected returns whether the transaction is protected from replay protection.
func (tx *Transaction) Protected() bool {
return isProtectedV(tx.data.V)

@ -112,7 +112,7 @@ while IFS='' read -r line || [[ -n "$line" ]]; do
./bin/benchmark -ip $ip -port $port -config_file $config -log_folder $log_folder $DB -min_peers $MIN &
else
./bin/benchmark -ip $ip -port $port -log_folder $log_folder $DB $PEER -min_peers $MIN &
sleep 1
sleep 0.5
fi
fi
done < $config

@ -1,6 +1,7 @@
package main
import (
"encoding/hex"
"fmt"
"github.com/ethereum/go-ethereum/common"
"log"
@ -86,7 +87,7 @@ func main() {
}
txs := make([]*types.Transaction, 10)
worker := worker.New(params.TestChainConfig, chain, consensus.NewFaker(), crypto.PubkeyToAddress(testBankKey.PublicKey))
worker := worker.New(params.TestChainConfig, chain, consensus.NewFaker(), crypto.PubkeyToAddress(testBankKey.PublicKey), 0)
nonce := worker.GetCurrentState().GetNonce(crypto.PubkeyToAddress(testBankKey.PublicKey))
for i := range txs {
randomUserKey, _ := crypto.GenerateKey()
@ -116,7 +117,7 @@ func main() {
// return address(this).balance;
//}
//}
contractData := "0x60806040526706f05b59d3b2000060015560028054600160a060020a031916331790556101aa806100316000396000f3fe608060405260043610610045577c0100000000000000000000000000000000000000000000000000000000600035046327c78c42811461004a5780634ddd108a1461008c575b600080fd5b34801561005657600080fd5b5061008a6004803603602081101561006d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166100b3565b005b34801561009857600080fd5b506100a1610179565b60408051918252519081900360200190f35b60025473ffffffffffffffffffffffffffffffffffffffff1633146100d757600080fd5b600154303110156100e757600080fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526020819052604090205460ff161561011a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260208190526040808220805460ff1916600190811790915554905181156108fc0292818181858888f19350505050158015610175573d6000803e3d6000fd5b5050565b30319056fea165627a7a72305820fc2f7280f3590bd63f7b13a34411e0086c18e5a947b4437759ee79fbc566782f0029"
contractData := "0x60806040526802b5e3af16b188000060015560028054600160a060020a031916331790556101aa806100326000396000f3fe608060405260043610610045577c0100000000000000000000000000000000000000000000000000000000600035046327c78c42811461004a5780634ddd108a1461008c575b600080fd5b34801561005657600080fd5b5061008a6004803603602081101561006d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166100b3565b005b34801561009857600080fd5b506100a1610179565b60408051918252519081900360200190f35b60025473ffffffffffffffffffffffffffffffffffffffff1633146100d757600080fd5b600154303110156100e757600080fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526020819052604090205460ff161561011a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260208190526040808220805460ff1916600190811790915554905181156108fc0292818181858888f19350505050158015610175573d6000803e3d6000fd5b5050565b30319056fea165627a7a7230582003d799bcee73e96e0f40ca432d9c3d2aa9c00a1eba8d00877114a0d7234790ce0029"
_ = contractData
dataEnc := common.FromHex(contractData)
@ -140,15 +141,19 @@ func main() {
}
fmt.Println(contractAddress)
var address common.Address
bytes, err := hex.DecodeString("ac51b997a3a17fa18e46baceb32fcab9acc93917")
address.SetBytes(bytes)
receipts := worker.GetCurrentReceipts()
fmt.Println(receipts[len(receipts)-1].ContractAddress)
fmt.Println(receipts[len(receipts)-1])
fmt.Println(state.GetNonce(testBankAddress))
fmt.Println(state.GetNonce(contractAddress))
fmt.Println(testBankKey)
fmt.Println(state.GetBalance(contractAddress))
fmt.Println(state.GetBalance(address))
fmt.Println(state.GetCodeHash(contractAddress))
callData := "0x27c78c4200000000000000000000000024182601fe6e2e5da0b831496cc0489b7173b44f"
callData := "0x27c78c42000000000000000000000000ac51b997a3a17fa18e46baceb32fcab9acc93917" //24182601fe6e2e5da0b831496cc0489b7173b44f"
callEnc := common.FromHex(callData)
tx, _ = types.SignTx(types.NewTransaction(nonce+uint64(11), contractAddress, 0, big.NewInt(0), params.TxGasContractCreation*10, nil, callEnc), types.HomesteadSigner{}, testBankKey)
@ -160,7 +165,7 @@ func main() {
fmt.Println(receipts[len(receipts)-1].ContractAddress)
fmt.Println(receipts[len(receipts)-1])
fmt.Println(state.GetNonce(testBankAddress))
fmt.Println(state.GetNonce(contractAddress))
fmt.Println(state.GetBalance(contractAddress))
fmt.Println(state.GetBalance(address))
fmt.Println(state.GetCodeHash(contractAddress))
}

@ -4,6 +4,7 @@ import (
"bytes"
"crypto/ecdsa"
"encoding/gob"
"encoding/hex"
"fmt"
"math/big"
"math/rand"
@ -134,6 +135,7 @@ type Node struct {
// Test only
TestBankKeys []*ecdsa.PrivateKey
ContractKeys []*ecdsa.PrivateKey
ContractAddresses []common.Address
// The p2p host used to send/receive p2p messages
host host.Host
@ -259,17 +261,6 @@ func DeserializeNode(d []byte) *NetworkNode {
return &wn
}
//AddSmartContractsToPendingTransactions adds the faucet contract the genesis block.
func (node *Node) AddSmartContractsToPendingTransactions() {
// Add a contract deployment transactionv
priKey := node.ContractKeys[0]
contractData := "0x608060405234801561001057600080fd5b506040516020806104c08339810180604052602081101561003057600080fd5b505160008054600160a060020a0319163317808255600160a060020a031681526001602081905260409091205560ff811661006c600282610073565b50506100bd565b8154818355818111156100975760008381526020902061009791810190830161009c565b505050565b6100ba91905b808211156100b657600081556001016100a2565b5090565b90565b6103f4806100cc6000396000f3fe60806040526004361061005b577c010000000000000000000000000000000000000000000000000000000060003504635c19a95c8114610060578063609ff1bd146100955780639e7b8d61146100c0578063b3f98adc146100f3575b600080fd5b34801561006c57600080fd5b506100936004803603602081101561008357600080fd5b5035600160a060020a0316610120565b005b3480156100a157600080fd5b506100aa610280565b6040805160ff9092168252519081900360200190f35b3480156100cc57600080fd5b50610093600480360360208110156100e357600080fd5b5035600160a060020a03166102eb565b3480156100ff57600080fd5b506100936004803603602081101561011657600080fd5b503560ff16610348565b3360009081526001602081905260409091209081015460ff1615610144575061027d565b5b600160a060020a0382811660009081526001602081905260409091200154620100009004161580159061019c5750600160a060020a0382811660009081526001602081905260409091200154620100009004163314155b156101ce57600160a060020a039182166000908152600160208190526040909120015462010000900490911690610145565b600160a060020a0382163314156101e5575061027d565b6001818101805460ff1916821775ffffffffffffffffffffffffffffffffffffffff0000191662010000600160a060020a0386169081029190911790915560009081526020829052604090209081015460ff16156102725781546001820154600280549091610100900460ff1690811061025b57fe5b60009182526020909120018054909101905561027a565b815481540181555b50505b50565b600080805b60025460ff821610156102e6578160028260ff168154811015156102a557fe5b906000526020600020016000015411156102de576002805460ff83169081106102ca57fe5b906000526020600020016000015491508092505b600101610285565b505090565b600054600160a060020a0316331415806103215750600160a060020a0381166000908152600160208190526040909120015460ff165b1561032b5761027d565b600160a060020a0316600090815260016020819052604090912055565b3360009081526001602081905260409091209081015460ff1680610371575060025460ff831610155b1561037c575061027d565b6001818101805460ff191690911761ff00191661010060ff8516908102919091179091558154600280549192909181106103b257fe5b600091825260209091200180549091019055505056fea165627a7a72305820164189ef302b4648e01e22456b0a725191604cb63ee472f230ef6a2d17d702f900290000000000000000000000000000000000000000000000000000000000000002"
dataEnc := common.FromHex(contractData)
// Unsigned transaction to avoid the case of transaction address.
mycontracttx, _ := types.SignTx(types.NewContractCreation(uint64(0), 0, big.NewInt(1000000), params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, priKey)
node.addPendingTransactionsAccount(types.Transactions{mycontracttx})
}
// New creates a new node.
func New(host host.Host, consensus *bft.Consensus, db *hdb.LDBDatabase) *Node {
node := Node{}
@ -314,16 +305,18 @@ func New(host host.Host, consensus *bft.Consensus, db *hdb.LDBDatabase) *Node {
for i := 0; i < 100; i++ {
testBankKey, _ := ecdsa.GenerateKey(crypto.S256(), reader)
testBankAddress := crypto.PubkeyToAddress(testBankKey.PublicKey)
testBankFunds := big.NewInt(8000000000000000000)
//fmt.Println(crypto.PubkeyToAddress(testBankKey.PublicKey).Hex())
//fmt.Println(hex.EncodeToString(crypto.FromECDSA(testBankKey)))
testBankFunds := big.NewInt(1000)
testBankFunds = testBankFunds.Mul(testBankFunds, big.NewInt(params.Ether))
fmt.Println(crypto.PubkeyToAddress(testBankKey.PublicKey).Hex())
fmt.Println(hex.EncodeToString(crypto.FromECDSA(testBankKey)))
genesisAloc[testBankAddress] = core.GenesisAccount{Balance: testBankFunds}
node.TestBankKeys = append(node.TestBankKeys, testBankKey)
}
contractKey, _ := ecdsa.GenerateKey(crypto.S256(), reader)
contractAddress := crypto.PubkeyToAddress(contractKey.PublicKey)
contractFunds := big.NewInt(8000000000000000000)
contractFunds := big.NewInt(9000000)
contractFunds = contractFunds.Mul(contractFunds, big.NewInt(params.Ether))
genesisAloc[contractAddress] = core.GenesisAccount{Balance: contractFunds}
node.ContractKeys = append(node.ContractKeys, contractKey)
@ -342,9 +335,9 @@ func New(host host.Host, consensus *bft.Consensus, db *hdb.LDBDatabase) *Node {
//This one is not used --- RJ.
node.TxPool = core.NewTxPool(core.DefaultTxPoolConfig, params.TestChainConfig, chain)
node.BlockChannelAccount = make(chan *types.Block)
node.Worker = worker.New(params.TestChainConfig, chain, node.Consensus, pki.GetAddressFromPublicKey(node.SelfPeer.PubKey))
//Initialize the pending transactions with smart contract transactions
//node.AddSmartContractsToPendingTransactions()
node.Worker = worker.New(params.TestChainConfig, chain, node.Consensus, pki.GetAddressFromPublicKey(node.SelfPeer.PubKey), node.Consensus.ShardID)
node.AddSmartContractsToPendingTransactions()
}
if consensus != nil && consensus.IsLeader {
@ -434,14 +427,37 @@ func (node *Node) GetSyncingPeers() []p2p.Peer {
return res
}
//AddSmartContractsToPendingTransactions adds the faucet contract the genesis block.
func (node *Node) AddSmartContractsToPendingTransactions() {
// Add a contract deployment transactionv
priKey := node.ContractKeys[0]
contractData := "0x6080604052678ac7230489e8000060015560028054600160a060020a031916331790556101aa806100316000396000f3fe608060405260043610610045577c0100000000000000000000000000000000000000000000000000000000600035046327c78c42811461004a5780634ddd108a1461008c575b600080fd5b34801561005657600080fd5b5061008a6004803603602081101561006d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166100b3565b005b34801561009857600080fd5b506100a1610179565b60408051918252519081900360200190f35b60025473ffffffffffffffffffffffffffffffffffffffff1633146100d757600080fd5b600154303110156100e757600080fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526020819052604090205460ff161561011a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260208190526040808220805460ff1916600190811790915554905181156108fc0292818181858888f19350505050158015610175573d6000803e3d6000fd5b5050565b30319056fea165627a7a723058203e799228fee2fa7c5d15e71c04267a0cc2687c5eff3b48b98f21f355e1064ab30029"
dataEnc := common.FromHex(contractData)
// Unsigned transaction to avoid the case of transaction address.
contractFunds := big.NewInt(8000000)
contractFunds = contractFunds.Mul(contractFunds, big.NewInt(params.Ether))
mycontracttx, _ := types.SignTx(types.NewContractCreation(uint64(0), node.Consensus.ShardID, contractFunds, params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, priKey)
node.ContractAddresses = append(node.ContractAddresses, crypto.CreateAddress(crypto.PubkeyToAddress(priKey.PublicKey), uint64(0)))
fmt.Println(node.ContractAddresses[0].Hex())
node.addPendingTransactionsAccount(types.Transactions{mycontracttx})
}
//CallFaucetContract invokes the faucet contract to give the walletAddress initial money
func (node *Node) CallFaucetContract(contractAddress common.Address, walletAddress common.Address) {
nonce := node.Worker.GetCurrentState().GetNonce(crypto.PubkeyToAddress(node.ContractKeys[0].PublicKey))
func (node *Node) CallFaucetContract(walletAddress common.Address) common.Hash {
state, err := node.Chain.State()
if err != nil {
log.Error("Failed to get chain state", "Error", err)
}
nonce := state.GetNonce(crypto.PubkeyToAddress(node.ContractKeys[0].PublicKey))
callingFunction := "0x27c78c42000000000000000000000000"
contractData := callingFunction + walletAddress.Hex()
contractData := callingFunction + hex.EncodeToString(walletAddress.Bytes())
dataEnc := common.FromHex(contractData)
tx, _ := types.SignTx(types.NewTransaction(nonce, contractAddress, node.Consensus.ShardID, big.NewInt(7000000000000000000), params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, node.ContractKeys[0])
tx, _ := types.SignTx(types.NewTransaction(nonce, node.ContractAddresses[0], node.Consensus.ShardID, big.NewInt(0), params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, node.ContractKeys[0])
node.addPendingTransactionsAccount(types.Transactions{tx})
return tx.Hash()
}
// JoinShard helps a new node to join a shard.
@ -481,7 +497,7 @@ func (node *Node) SupportClient() {
// InitClientServer initializes client server.
func (node *Node) InitClientServer() {
node.clientServer = clientService.NewServer(node.Chain.State)
node.clientServer = clientService.NewServer(node.Chain.State, node.CallFaucetContract)
}
// StartClientServer starts client server.

@ -331,6 +331,7 @@ func (node *Node) WaitForConsensusReady(readySignal chan struct{}) {
// WaitForConsensusReadyAccount ...
func (node *Node) WaitForConsensusReadyAccount(readySignal chan struct{}) {
node.log.Debug("Waiting for Consensus ready", "node", node)
time.Sleep(10 * time.Second)
var newBlock *types.Block
timeoutCount := 0

@ -37,6 +37,8 @@ type Worker struct {
gasFloor uint64
gasCeil uint64
shardID uint32
}
// SelectTransactionsForNewBlock selects transactions for new block.
@ -48,6 +50,9 @@ func (w *Worker) SelectTransactionsForNewBlock(txs types.Transactions, maxNumTxs
unselected := types.Transactions{}
invalid := types.Transactions{}
for _, tx := range txs {
if tx.ShardID() != w.shardID {
invalid = append(invalid, tx)
}
snap := w.current.state.Snapshot()
_, err := w.commitTransaction(tx, w.coinbase)
if len(selected) > maxNumTxs {
@ -151,7 +156,7 @@ func (w *Worker) Commit() (*types.Block, error) {
}
// New ...
func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus.Engine, coinbase common.Address) *Worker {
func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus.Engine, coinbase common.Address, shardID uint32) *Worker {
worker := &Worker{
config: config,
chain: chain,
@ -160,6 +165,7 @@ func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus.En
worker.gasFloor = 0
worker.gasCeil = 1000000000000000
worker.coinbase = coinbase
worker.shardID = shardID
parent := worker.chain.CurrentBlock()
num := parent.Number()

Loading…
Cancel
Save