Merge remote-tracking branch 'remotes/peter/bugfix/sendTransactionAsync-updates' into geth-upgrade-1.8.12

# Conflicts:
#	internal/ethapi/api.go
This commit is contained in:
amalraj.manigmail.com 2018-09-28 15:51:27 +08:00
commit d35f6e2c5e
2 changed files with 47 additions and 87 deletions

View File

@ -1164,8 +1164,11 @@ type SendTxArgs struct {
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input"`
//Quorum
PrivateFrom string `json:"privateFrom"`
PrivateFor []string `json:"privateFor"`
PrivateTxType string `json:"restriction"`
//End-Quorum
}
// setDefaults is a helper function that fills in default values for unspecified tx fields.
@ -1191,21 +1194,11 @@ func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
}
args.Nonce = (*hexutil.Uint64)(&nonce)
}
if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) {
return errors.New(`Both "data" and "input" are set and not equal. Please use "input" to pass transaction call data.`)
}
if args.To == nil {
// Contract creation
var input []byte
if args.Data != nil {
input = *args.Data
} else if args.Input != nil {
input = *args.Input
}
if len(input) == 0 {
return errors.New(`contract creation without any data provided`)
}
//Quorum
if args.PrivateTxType == "" {
args.PrivateTxType = "restricted"
}
//End-Quorum
return nil
}
@ -1571,6 +1564,7 @@ func (s *PublicNetAPI) Version() string {
return fmt.Sprintf("%d", s.networkVersion)
}
// Quorum
// Please note: This is a temporary integration to improve performance in high-latency
// environments when sending many private transactions. It will be removed at a later
// date when account management is handled outside Ethereum.
@ -1580,85 +1574,49 @@ type AsyncSendTxArgs struct {
CallbackUrl string `json:"callbackUrl"`
}
type AsyncResult struct {
type AsyncResultSuccess struct {
Id string `json:"id,omitempty"`
TxHash common.Hash `json:"txHash"`
}
type AsyncResultFailure struct {
Id string `json:"id,omitempty"`
Error string `json:"error"`
}
type Async struct {
sync.Mutex
sem chan struct{}
}
func (s *PublicTransactionPoolAPI) send(ctx context.Context, asyncArgs AsyncSendTxArgs) {
txHash, err := s.SendTransaction(ctx, asyncArgs.SendTxArgs)
func (a *Async) send(ctx context.Context, s *PublicTransactionPoolAPI, asyncArgs AsyncSendTxArgs) {
res := new(AsyncResult)
if asyncArgs.CallbackUrl != "" {
defer func() {
buf := new(bytes.Buffer)
err := json.NewEncoder(buf).Encode(res)
if err != nil {
log.Info("Error encoding callback JSON: %v", err)
return
}
_, err = http.Post(asyncArgs.CallbackUrl, "application/json", buf)
if err != nil {
log.Info("Error sending callback: %v", err)
return
}
}()
}
args := asyncArgs.SendTxArgs
err := args.setDefaults(ctx, s.b)
if err != nil {
log.Info("Async.send: Error doing setDefaults: %v", err)
res.Error = err.Error()
return
}
b, err := private.P.Send([]byte(*args.Data), args.PrivateFrom, args.PrivateFor)
if err != nil {
log.Info("Error running Private.P.Send", "err", err)
res.Error = err.Error()
return
}
res.TxHash, err = a.save(ctx, s, args, b)
if err != nil {
res.Error = err.Error()
}
}
func (a *Async) save(ctx context.Context, s *PublicTransactionPoolAPI, args SendTxArgs, data []byte) (common.Hash, error) {
a.Lock()
defer a.Unlock()
if args.Nonce == nil {
nonce, err := s.b.GetPoolNonce(ctx, args.From)
//don't need to nil check this since id is required for every geth rpc call
//even though this is stated in the specification as an "optional" parameter
jsonId := ctx.Value("id").(*json.RawMessage)
id := string(*jsonId)
var resultResponse interface{}
if err != nil {
return common.Hash{}, err
resultResponse = &AsyncResultFailure{Id: id, Error: err.Error()}
} else {
resultResponse = &AsyncResultSuccess{Id: id, TxHash: txHash}
}
buf := new(bytes.Buffer)
err := json.NewEncoder(buf).Encode(resultResponse)
if err != nil {
log.Info("Error encoding callback JSON: %v", err)
return
}
_, err = http.Post(asyncArgs.CallbackUrl, "application/json", buf)
if err != nil {
log.Info("Error sending callback: %v", err)
return
}
args.Nonce = (*hexutil.Uint64)(&nonce)
}
var tx *types.Transaction
if args.To == nil {
tx = types.NewContractCreation((uint64)(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), data)
} else {
tx = types.NewTransaction((uint64)(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), data)
}
signed, err := s.sign(args.From, tx)
if err != nil {
return common.Hash{}, err
}
return submitTransaction(ctx, s.b, signed, args.PrivateFor != nil)
}
func newAsync(n int) *Async {
a := &Async{
sem: make(chan struct{}, n),
}
return a
}
var async = newAsync(100)
// SendTransactionAsync creates a transaction for the given argument, signs it, and
// submits it to the transaction pool. This call returns immediately to allow sending
@ -1671,12 +1629,9 @@ var async = newAsync(100)
// Please note: This is a temporary integration to improve performance in high-latency
// environments when sending many private transactions. It will be removed at a later
// date when account management is handled outside Ethereum.
func (s *PublicTransactionPoolAPI) SendTransactionAsync(ctx context.Context, args AsyncSendTxArgs) {
async.sem <- struct{}{}
go func() {
async.send(ctx, s, args)
<-async.sem
}()
func (s *PublicTransactionPoolAPI) SendTransactionAsync(ctx context.Context, args AsyncSendTxArgs) (common.Hash, error){
go s.send(ctx, args)
return common.Hash{}, nil
}
// GetQuorumPayload returns the contents of a private transaction
@ -1703,3 +1658,4 @@ func (s *PublicBlockChainAPI) GetQuorumPayload(digestHex string) (string, error)
}
return fmt.Sprintf("0x%x", data), nil
}
//End-Quorum

View File

@ -300,9 +300,13 @@ func (s *Server) handle(ctx context.Context, codec ServerCodec, req *serverReque
return codec.CreateErrorResponse(&req.id, rpcErr), nil
}
//Quorum
//Pass the request ID to the method as part of the context, in case the method needs it later
contextWithId := context.WithValue(ctx, "id", req.id)
//End-Quorum
arguments := []reflect.Value{req.callb.rcvr}
if req.callb.hasCtx {
arguments = append(arguments, reflect.ValueOf(ctx))
arguments = append(arguments, reflect.ValueOf(contextWithId))
}
if len(req.args) > 0 {
arguments = append(arguments, req.args...)