Merge branch 'next' of github.com:filecoin-project/go-lotus into next
This commit is contained in:
commit
c8046f4597
@ -350,11 +350,11 @@ type RetrievalOrder struct {
|
||||
}
|
||||
|
||||
type InvocResult struct {
|
||||
Msg *types.Message
|
||||
MsgRct *types.MessageReceipt
|
||||
InternalExecutions []*types.ExecutionResult
|
||||
Error string
|
||||
Duration time.Duration
|
||||
Msg *types.Message
|
||||
MsgRct *types.MessageReceipt
|
||||
ExecutionTrace types.ExecutionTrace
|
||||
Error string
|
||||
Duration time.Duration
|
||||
}
|
||||
|
||||
type MethodCall struct {
|
||||
|
@ -93,7 +93,7 @@ func init() {
|
||||
addExample(build.APIVersion)
|
||||
addExample(api.PCHInbound)
|
||||
addExample(time.Minute)
|
||||
addExample(&types.ExecutionResult{
|
||||
addExample(&types.ExecutionTrace{
|
||||
Msg: exampleValue(reflect.TypeOf(&types.Message{})).(*types.Message),
|
||||
MsgRct: exampleValue(reflect.TypeOf(&types.MessageReceipt{})).(*types.MessageReceipt),
|
||||
})
|
||||
|
@ -62,11 +62,11 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
|
||||
}
|
||||
|
||||
return &api.InvocResult{
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
InternalExecutions: ret.InternalExecutions,
|
||||
Error: errs,
|
||||
Duration: ret.Duration,
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
ExecutionTrace: ret.ExecutionTrace,
|
||||
Error: errs,
|
||||
Duration: ret.Duration,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
@ -121,10 +121,10 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
|
||||
var trace []*api.InvocResult
|
||||
st, _, err := sm.computeTipSetState(ctx, ts.Blocks(), func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||
ir := &api.InvocResult{
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
InternalExecutions: ret.InternalExecutions,
|
||||
Duration: ret.Duration,
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
ExecutionTrace: ret.ExecutionTrace,
|
||||
Duration: ret.Duration,
|
||||
}
|
||||
if ret.ActorErr != nil {
|
||||
ir.Error = ret.ActorErr.Error()
|
||||
|
@ -2,11 +2,11 @@ package types
|
||||
|
||||
import "time"
|
||||
|
||||
type ExecutionResult struct {
|
||||
type ExecutionTrace struct {
|
||||
Msg *Message
|
||||
MsgRct *MessageReceipt
|
||||
Error string
|
||||
Duration time.Duration
|
||||
|
||||
Subcalls []*ExecutionResult
|
||||
Subcalls []ExecutionTrace
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
@ -51,10 +50,10 @@ type Runtime struct {
|
||||
origin address.Address
|
||||
originNonce uint64
|
||||
|
||||
internalExecutions []*types.ExecutionResult
|
||||
numActorsCreated uint64
|
||||
allowInternal bool
|
||||
callerValidated bool
|
||||
executionTrace types.ExecutionTrace
|
||||
numActorsCreated uint64
|
||||
allowInternal bool
|
||||
callerValidated bool
|
||||
}
|
||||
|
||||
func (rt *Runtime) TotalFilCircSupply() abi.TokenAmount {
|
||||
@ -368,7 +367,6 @@ func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars
|
||||
}
|
||||
|
||||
func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
|
||||
start := time.Now()
|
||||
ctx, span := trace.StartSpan(rt.ctx, "vmc.Send")
|
||||
defer span.End()
|
||||
if span.IsRecordingEvents() {
|
||||
@ -401,27 +399,10 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum,
|
||||
}
|
||||
}
|
||||
|
||||
mr := types.MessageReceipt{
|
||||
ExitCode: aerrors.RetCode(errSend),
|
||||
Return: ret,
|
||||
GasUsed: 0,
|
||||
}
|
||||
|
||||
er := types.ExecutionResult{
|
||||
Msg: msg,
|
||||
MsgRct: &mr,
|
||||
Duration: time.Since(start),
|
||||
}
|
||||
|
||||
if errSend != nil {
|
||||
er.Error = errSend.Error()
|
||||
}
|
||||
|
||||
if subrt != nil {
|
||||
er.Subcalls = subrt.internalExecutions
|
||||
rt.numActorsCreated = subrt.numActorsCreated
|
||||
}
|
||||
rt.internalExecutions = append(rt.internalExecutions, &er)
|
||||
rt.executionTrace.Subcalls = append(rt.executionTrace.Subcalls, subrt.executionTrace) //&er)
|
||||
return ret, errSend
|
||||
}
|
||||
|
||||
@ -504,13 +485,13 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
|
||||
}
|
||||
|
||||
func (rt *Runtime) ChargeGas(toUse int64) {
|
||||
err := rt.chargeGasSafe(toUse)
|
||||
err := rt.chargeGasInternal(toUse)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *Runtime) chargeGasSafe(toUse int64) aerrors.ActorError {
|
||||
func (rt *Runtime) chargeGasInternal(toUse int64) aerrors.ActorError {
|
||||
if rt.gasUsed+toUse > rt.gasAvailable {
|
||||
rt.gasUsed = rt.gasAvailable
|
||||
return aerrors.Newf(exitcode.SysErrOutOfGas, "not enough gas: used=%d, available=%d", rt.gasUsed, rt.gasAvailable)
|
||||
@ -519,6 +500,10 @@ func (rt *Runtime) chargeGasSafe(toUse int64) aerrors.ActorError {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rt *Runtime) chargeGasSafe(toUse int64) aerrors.ActorError {
|
||||
return rt.chargeGasInternal(toUse)
|
||||
}
|
||||
|
||||
func (rt *Runtime) Pricelist() Pricelist {
|
||||
return rt.pricelist
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.Consen
|
||||
// (b) time-offset mining fault
|
||||
// strictly speaking no need to compare heights based on double fork mining check above,
|
||||
// but at same height this would be a different fault.
|
||||
if !types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height {
|
||||
if types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height {
|
||||
consensusFault = &runtime.ConsensusFault{
|
||||
Target: blockA.Miner,
|
||||
Epoch: blockB.Height,
|
||||
@ -159,7 +159,7 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.Consen
|
||||
}
|
||||
|
||||
if sigErr := ss.VerifyBlockSig(&blockB); sigErr != nil {
|
||||
return nil, xerrors.Errorf("cannot verify first block sig: %w", sigErr)
|
||||
return nil, xerrors.Errorf("cannot verify second block sig: %w", sigErr)
|
||||
}
|
||||
|
||||
return consensusFault, nil
|
||||
|
@ -102,6 +102,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres
|
||||
pricelist: PricelistByEpoch(vm.blockHeight),
|
||||
allowInternal: true,
|
||||
callerValidated: false,
|
||||
executionTrace: types.ExecutionTrace{Msg: msg},
|
||||
}
|
||||
|
||||
rt.cst = &cbor.BasicIpldStore{
|
||||
@ -163,14 +164,16 @@ type Rand interface {
|
||||
|
||||
type ApplyRet struct {
|
||||
types.MessageReceipt
|
||||
ActorErr aerrors.ActorError
|
||||
Penalty types.BigInt
|
||||
InternalExecutions []*types.ExecutionResult
|
||||
Duration time.Duration
|
||||
ActorErr aerrors.ActorError
|
||||
Penalty types.BigInt
|
||||
ExecutionTrace types.ExecutionTrace
|
||||
Duration time.Duration
|
||||
}
|
||||
|
||||
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
||||
gasCharge int64) ([]byte, aerrors.ActorError, *Runtime) {
|
||||
start := time.Now()
|
||||
|
||||
st := vm.cstate
|
||||
gasUsed := gasCharge
|
||||
|
||||
@ -191,35 +194,50 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
||||
}()
|
||||
}
|
||||
|
||||
if aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method)); aerr != nil {
|
||||
return nil, aerrors.Wrap(aerr, "not enough gas for method invocation"), rt
|
||||
}
|
||||
ret, err := func() ([]byte, aerrors.ActorError) {
|
||||
if aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method)); aerr != nil {
|
||||
return nil, aerrors.Wrap(aerr, "not enough gas for method invocation")
|
||||
}
|
||||
|
||||
toActor, err := st.GetActor(msg.To)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, init_.ErrAddressNotFound) {
|
||||
a, err := TryCreateAccountActor(rt, msg.To)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrapf(err, "could not create account"), rt
|
||||
toActor, err := st.GetActor(msg.To)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, init_.ErrAddressNotFound) {
|
||||
a, err := TryCreateAccountActor(rt, msg.To)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrapf(err, "could not create account")
|
||||
}
|
||||
toActor = a
|
||||
} else {
|
||||
return nil, aerrors.Escalate(err, "getting actor")
|
||||
}
|
||||
toActor = a
|
||||
} else {
|
||||
return nil, aerrors.Escalate(err, "getting actor"), rt
|
||||
}
|
||||
}
|
||||
|
||||
if types.BigCmp(msg.Value, types.NewInt(0)) != 0 {
|
||||
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
|
||||
return nil, aerrors.Wrap(err, "failed to transfer funds"), nil
|
||||
if types.BigCmp(msg.Value, types.NewInt(0)) != 0 {
|
||||
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
|
||||
return nil, aerrors.Wrap(err, "failed to transfer funds")
|
||||
}
|
||||
}
|
||||
|
||||
if msg.Method != 0 {
|
||||
var ret []byte
|
||||
ret, err := vm.Invoke(toActor, rt, msg.Method, msg.Params)
|
||||
return ret, err
|
||||
}
|
||||
return nil, nil
|
||||
}()
|
||||
|
||||
mr := types.MessageReceipt{
|
||||
ExitCode: aerrors.RetCode(err),
|
||||
Return: ret,
|
||||
GasUsed: rt.gasUsed,
|
||||
}
|
||||
rt.executionTrace.MsgRct = &mr
|
||||
rt.executionTrace.Duration = time.Since(start)
|
||||
if err != nil {
|
||||
rt.executionTrace.Error = err.Error()
|
||||
}
|
||||
|
||||
if msg.Method != 0 {
|
||||
ret, err := vm.Invoke(toActor, rt, msg.Method, msg.Params)
|
||||
return ret, err, rt
|
||||
}
|
||||
|
||||
return nil, nil, rt
|
||||
return ret, err, rt
|
||||
}
|
||||
|
||||
func checkMessage(msg *types.Message) error {
|
||||
@ -250,10 +268,10 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap
|
||||
Return: ret,
|
||||
GasUsed: 0,
|
||||
},
|
||||
ActorErr: actorErr,
|
||||
InternalExecutions: rt.internalExecutions,
|
||||
Penalty: types.NewInt(0),
|
||||
Duration: time.Since(start),
|
||||
ActorErr: actorErr,
|
||||
ExecutionTrace: rt.executionTrace,
|
||||
Penalty: types.NewInt(0),
|
||||
Duration: time.Since(start),
|
||||
}, actorErr
|
||||
}
|
||||
|
||||
@ -419,10 +437,10 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
||||
Return: ret,
|
||||
GasUsed: gasUsed,
|
||||
},
|
||||
ActorErr: actorErr,
|
||||
InternalExecutions: rt.internalExecutions,
|
||||
Penalty: types.NewInt(0),
|
||||
Duration: time.Since(start),
|
||||
ActorErr: actorErr,
|
||||
ExecutionTrace: rt.executionTrace,
|
||||
Penalty: types.NewInt(0),
|
||||
Duration: time.Since(start),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
14
cli/state.go
14
cli/state.go
@ -930,14 +930,14 @@ var stateComputeStateCmd = &cli.Command{
|
||||
if cctx.Bool("show-trace") {
|
||||
for _, ir := range stout.Trace {
|
||||
fmt.Printf("%s\t%s\t%s\t%d\t%x\t%d\t%x\n", ir.Msg.From, ir.Msg.To, ir.Msg.Value, ir.Msg.Method, ir.Msg.Params, ir.MsgRct.ExitCode, ir.MsgRct.Return)
|
||||
printInternalExecutions("\t", ir.InternalExecutions)
|
||||
printInternalExecutions("\t", ir.ExecutionTrace.Subcalls)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func printInternalExecutions(prefix string, trace []*types.ExecutionResult) {
|
||||
func printInternalExecutions(prefix string, trace []types.ExecutionTrace) {
|
||||
for _, im := range trace {
|
||||
fmt.Printf("%s%s\t%s\t%s\t%d\t%x\t%d\t%x\n", prefix, im.Msg.From, im.Msg.To, im.Msg.Value, im.Msg.Method, im.Msg.Params, im.MsgRct.ExitCode, im.MsgRct.Return)
|
||||
printInternalExecutions(prefix+"\t", im.Subcalls)
|
||||
@ -1027,11 +1027,9 @@ func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func(
|
||||
fmt.Printf(`<div class="error">Error: <pre>%s</pre></div>`, ir.Error)
|
||||
}
|
||||
|
||||
if len(ir.InternalExecutions) > 0 {
|
||||
fmt.Println("<div>Internal executions:</div>")
|
||||
if err := printInternalExecutionsHtml(cid.String(), ir.InternalExecutions, getCode); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("<div>Execution trace:</div>")
|
||||
if err := printInternalExecutionsHtml(cid.String(), ir.ExecutionTrace.Subcalls, getCode); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("</div>")
|
||||
}
|
||||
@ -1041,7 +1039,7 @@ func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func(
|
||||
return nil
|
||||
}
|
||||
|
||||
func printInternalExecutionsHtml(hashName string, trace []*types.ExecutionResult, getCode func(addr address.Address) (cid.Cid, error)) error {
|
||||
func printInternalExecutionsHtml(hashName string, trace []types.ExecutionTrace, getCode func(addr address.Address) (cid.Cid, error)) error {
|
||||
for i, im := range trace {
|
||||
hashName := fmt.Sprintf("%s-r%d", hashName, i)
|
||||
|
||||
|
3
go.sum
3
go.sum
@ -42,9 +42,11 @@ github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
|
||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||
github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
||||
@ -1575,6 +1577,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
// FromFile loads config from a specified file overriding defaults specified in
|
||||
// the def parameter. If file does not exist or is empty defaults are asummed.
|
||||
// the def parameter. If file does not exist or is empty defaults are assumed.
|
||||
func FromFile(path string, def interface{}) (interface{}, error) {
|
||||
file, err := os.Open(path)
|
||||
switch {
|
||||
|
@ -242,11 +242,11 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.
|
||||
}
|
||||
|
||||
return &api.InvocResult{
|
||||
Msg: m,
|
||||
MsgRct: &r.MessageReceipt,
|
||||
InternalExecutions: r.InternalExecutions,
|
||||
Error: errstr,
|
||||
Duration: r.Duration,
|
||||
Msg: m,
|
||||
MsgRct: &r.MessageReceipt,
|
||||
ExecutionTrace: r.ExecutionTrace,
|
||||
Error: errstr,
|
||||
Duration: r.Duration,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/ipfs/go-datastore"
|
||||
fslock "github.com/ipfs/go-fs-lock"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
@ -229,6 +230,7 @@ type fsLockedRepo struct {
|
||||
dsOnce sync.Once
|
||||
|
||||
storageLk sync.Mutex
|
||||
configLk sync.Mutex
|
||||
}
|
||||
|
||||
func (fsr *fsLockedRepo) Path() string {
|
||||
@ -265,12 +267,50 @@ func (fsr *fsLockedRepo) stillValid() error {
|
||||
}
|
||||
|
||||
func (fsr *fsLockedRepo) Config() (interface{}, error) {
|
||||
if err := fsr.stillValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fsr.configLk.Lock()
|
||||
defer fsr.configLk.Unlock()
|
||||
|
||||
return fsr.loadConfigFromDisk()
|
||||
}
|
||||
|
||||
func (fsr *fsLockedRepo) loadConfigFromDisk() (interface{}, error) {
|
||||
return config.FromFile(fsr.join(fsConfig), defConfForType(fsr.repoType))
|
||||
}
|
||||
|
||||
func (fsr *fsLockedRepo) SetConfig(c func(interface{})) error {
|
||||
if err := fsr.stillValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fsr.configLk.Lock()
|
||||
defer fsr.configLk.Unlock()
|
||||
|
||||
cfg, err := fsr.loadConfigFromDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// mutate in-memory representation of config
|
||||
c(cfg)
|
||||
|
||||
// buffer into which we write TOML bytes
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// encode now-mutated config as TOML and write to buffer
|
||||
err = toml.NewEncoder(buf).Encode(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// write buffer of TOML bytes to config file
|
||||
err = ioutil.WriteFile(fsr.join(fsConfig), buf.Bytes(), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fsr *fsLockedRepo) GetStorage() (stores.StorageConfig, error) {
|
||||
fsr.storageLk.Lock()
|
||||
defer fsr.storageLk.Unlock()
|
||||
|
@ -38,6 +38,7 @@ type LockedRepo interface {
|
||||
|
||||
// Returns config in this repo
|
||||
Config() (interface{}, error)
|
||||
SetConfig(func(interface{})) error
|
||||
|
||||
GetStorage() (stores.StorageConfig, error)
|
||||
SetStorage(func(*stores.StorageConfig)) error
|
||||
|
@ -30,8 +30,16 @@ type MemRepo struct {
|
||||
token *byte
|
||||
|
||||
datastore datastore.Datastore
|
||||
configF func(t RepoType) interface{}
|
||||
keystore map[string]types.KeyInfo
|
||||
|
||||
// given a repo type, produce the default config
|
||||
configF func(t RepoType) interface{}
|
||||
|
||||
// holds the current config value
|
||||
config struct {
|
||||
sync.Mutex
|
||||
val interface{}
|
||||
}
|
||||
}
|
||||
|
||||
type lockedMemRepo struct {
|
||||
@ -45,6 +53,10 @@ type lockedMemRepo struct {
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) GetStorage() (stores.StorageConfig, error) {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return stores.StorageConfig{}, err
|
||||
}
|
||||
|
||||
if lmem.sc == nil {
|
||||
lmem.sc = &stores.StorageConfig{StoragePaths: []stores.LocalPath{
|
||||
{Path: lmem.Path()},
|
||||
@ -55,6 +67,10 @@ func (lmem *lockedMemRepo) GetStorage() (stores.StorageConfig, error) {
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) SetStorage(c func(*stores.StorageConfig)) error {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = lmem.GetStorage()
|
||||
|
||||
c(lmem.sc)
|
||||
@ -221,11 +237,32 @@ func (lmem *lockedMemRepo) Config() (interface{}, error) {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lmem.mem.configF(lmem.t), nil
|
||||
|
||||
lmem.mem.config.Lock()
|
||||
defer lmem.mem.config.Unlock()
|
||||
|
||||
if lmem.mem.config.val == nil {
|
||||
lmem.mem.config.val = lmem.mem.configF(lmem.t)
|
||||
}
|
||||
|
||||
return lmem.mem.config.val, nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) Storage() (stores.StorageConfig, error) {
|
||||
panic("implement me")
|
||||
func (lmem *lockedMemRepo) SetConfig(c func(interface{})) error {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lmem.mem.config.Lock()
|
||||
defer lmem.mem.config.Unlock()
|
||||
|
||||
if lmem.mem.config.val == nil {
|
||||
lmem.mem.config.val = lmem.mem.configF(lmem.t)
|
||||
}
|
||||
|
||||
c(lmem.mem.config.val)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error {
|
||||
|
@ -9,6 +9,8 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func basicTest(t *testing.T, repo Repo) {
|
||||
@ -47,10 +49,23 @@ func basicTest(t *testing.T, repo Repo) {
|
||||
assert.NoError(t, err, "setting multiaddr shouldn't error")
|
||||
assert.Equal(t, ma, apima, "returned API multiaddr should be the same")
|
||||
|
||||
cfg, err := lrepo.Config()
|
||||
assert.Equal(t, config.DefaultFullNode(), cfg, "there should be a default config")
|
||||
c1, err := lrepo.Config()
|
||||
assert.Equal(t, config.DefaultFullNode(), c1, "there should be a default config")
|
||||
assert.NoError(t, err, "config should not error")
|
||||
|
||||
// mutate config and persist back to repo
|
||||
err = lrepo.SetConfig(func(c interface{}) {
|
||||
cfg := c.(*config.FullNode)
|
||||
cfg.Client.IpfsMAddr = "duvall"
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// load config and verify changes
|
||||
c2, err := lrepo.Config()
|
||||
require.NoError(t, err)
|
||||
cfg2 := c2.(*config.FullNode)
|
||||
require.Equal(t, cfg2.Client.IpfsMAddr, "duvall")
|
||||
|
||||
err = lrepo.Close()
|
||||
assert.NoError(t, err, "should be able to close")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user