github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/admin/commands/state_synchronization/execute_script.go (about)

     1  package state_synchronization
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"strconv"
     7  
     8  	"github.com/onflow/flow-go/admin"
     9  	"github.com/onflow/flow-go/admin/commands"
    10  	"github.com/onflow/flow-go/module/execution"
    11  )
    12  
    13  var _ commands.AdminCommand = (*ReadExecutionDataCommand)(nil)
    14  
    15  type scriptData struct {
    16  	height    uint64
    17  	script    []byte
    18  	arguments [][]byte
    19  }
    20  
    21  type ExecuteScriptCommand struct {
    22  	scriptExecutor execution.ScriptExecutor
    23  }
    24  
    25  func (e *ExecuteScriptCommand) Handler(ctx context.Context, req *admin.CommandRequest) (interface{}, error) {
    26  	d := req.ValidatorData.(*scriptData)
    27  
    28  	result, err := e.scriptExecutor.ExecuteAtBlockHeight(context.Background(), d.script, d.arguments, d.height)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  
    33  	return string(result), nil
    34  }
    35  
    36  // Validator validates the request.
    37  // Returns admin.InvalidAdminReqError for invalid/malformed requests.
    38  func (e *ExecuteScriptCommand) Validator(req *admin.CommandRequest) error {
    39  	input, ok := req.Data.(map[string]interface{})
    40  	if !ok {
    41  		return admin.NewInvalidAdminReqFormatError("expected map[string]any")
    42  	}
    43  
    44  	heightRaw, ok := input["height"]
    45  	if !ok {
    46  		return admin.NewInvalidAdminReqFormatError("missing required field 'height")
    47  	}
    48  
    49  	scriptRaw, ok := input["script"]
    50  	if !ok {
    51  		return admin.NewInvalidAdminReqFormatError("missing required field 'script")
    52  	}
    53  
    54  	argsRaw, ok := input["args"]
    55  	if !ok {
    56  		return admin.NewInvalidAdminReqFormatError("missing required field 'args")
    57  	}
    58  
    59  	heightStr, ok := heightRaw.(string)
    60  	if !ok {
    61  		return admin.NewInvalidAdminReqFormatError("'height' must be string")
    62  	}
    63  
    64  	height, err := strconv.ParseUint(heightStr, 10, 64)
    65  	if err != nil {
    66  		return admin.NewInvalidAdminReqFormatError("'height' must be valid uint64 value", err)
    67  	}
    68  
    69  	scriptStr, ok := scriptRaw.(string)
    70  	if !ok {
    71  		return admin.NewInvalidAdminReqFormatError("'script' must be string")
    72  	}
    73  
    74  	argsStr, ok := argsRaw.(string)
    75  	if !ok {
    76  		return admin.NewInvalidAdminReqFormatError("'args' must be string")
    77  	}
    78  
    79  	args := make([][]byte, 0)
    80  	err = json.Unmarshal([]byte(argsStr), &args)
    81  	if err != nil {
    82  		return admin.NewInvalidAdminReqFormatError("'args' not valid JSON", err)
    83  	}
    84  
    85  	req.ValidatorData = &scriptData{
    86  		height:    height,
    87  		script:    []byte(scriptStr),
    88  		arguments: args,
    89  	}
    90  
    91  	return nil
    92  }
    93  
    94  func NewExecuteScriptCommand(scripts execution.ScriptExecutor) commands.AdminCommand {
    95  	return &ExecuteScriptCommand{
    96  		scripts,
    97  	}
    98  }