Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad7c79d959 | ||
|
|
29e9e782c9 | ||
|
|
b284beaaef | ||
|
|
08134552a4 | ||
|
|
4b590e2102 | ||
|
|
41fce94db4 | ||
|
|
4efc29aa64 | ||
|
|
2cd3a052e3 | ||
|
|
bc87017ea5 | ||
|
|
dcdd1bc214 | ||
|
|
f11a7f8940 | ||
|
|
317a87d669 | ||
|
|
2a0660447a | ||
|
|
2bb89d9c30 | ||
|
|
ee6c0f8570 | ||
|
|
7362556c02 | ||
|
|
6550abdfcc | ||
|
|
ce17546a76 | ||
|
|
57d4c98d00 | ||
|
|
c71680ded8 | ||
|
|
1022ac5e2b | ||
|
|
b484d72c80 | ||
|
|
e2ff9027f9 | ||
|
|
dbd7ac5315 | ||
|
|
4ebc408a5a | ||
|
|
1152bb2e7b | ||
|
|
f48c6268f8 | ||
|
|
3738433abe | ||
|
|
02db37bf37 | ||
|
|
6e9a1f44ed | ||
|
|
8a3f91e655 | ||
|
|
c099317bb3 | ||
|
|
5d3314f121 | ||
|
|
7f33db90d8 | ||
|
|
35730637dc |
@@ -33,6 +33,9 @@ import (
|
||||
// * Generate openrpc blobs
|
||||
|
||||
type Gateway interface {
|
||||
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
|
||||
GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error)
|
||||
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
ChainPutObj(context.Context, blocks.Block) error
|
||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||
|
||||
@@ -726,6 +726,8 @@ type GatewayMethods struct {
|
||||
|
||||
EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) ``
|
||||
|
||||
GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) ``
|
||||
|
||||
GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) ``
|
||||
|
||||
MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) ``
|
||||
@@ -768,12 +770,16 @@ type GatewayMethods struct {
|
||||
|
||||
StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) ``
|
||||
|
||||
StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) ``
|
||||
|
||||
StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) ``
|
||||
|
||||
StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) ``
|
||||
|
||||
StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) ``
|
||||
|
||||
StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) ``
|
||||
|
||||
StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) ``
|
||||
|
||||
StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) ``
|
||||
@@ -4614,6 +4620,17 @@ func (s *GatewayStub) EthUnsubscribe(p0 context.Context, p1 ethtypes.EthSubscrip
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) {
|
||||
if s.Internal.GasEstimateGasPremium == nil {
|
||||
return *new(types.BigInt), ErrNotSupported
|
||||
}
|
||||
return s.Internal.GasEstimateGasPremium(p0, p1, p2, p3, p4)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) {
|
||||
return *new(types.BigInt), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) GasEstimateMessageGas(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) {
|
||||
if s.Internal.GasEstimateMessageGas == nil {
|
||||
return nil, ErrNotSupported
|
||||
@@ -4845,6 +4862,17 @@ func (s *GatewayStub) StateMinerProvingDeadline(p0 context.Context, p1 address.A
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) {
|
||||
if s.Internal.StateMinerSectorCount == nil {
|
||||
return *new(MinerSectors), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StateMinerSectorCount(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) {
|
||||
return *new(MinerSectors), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateNetworkName(p0 context.Context) (dtypes.NetworkName, error) {
|
||||
if s.Internal.StateNetworkName == nil {
|
||||
return *new(dtypes.NetworkName), ErrNotSupported
|
||||
@@ -4878,6 +4906,17 @@ func (s *GatewayStub) StateReadState(p0 context.Context, p1 address.Address, p2
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) {
|
||||
if s.Internal.StateReplay == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.StateReplay(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) {
|
||||
if s.Internal.StateSearchMsg == nil {
|
||||
return nil, ErrNotSupported
|
||||
|
||||
@@ -35,6 +35,9 @@ import (
|
||||
// * Generate openrpc blobs
|
||||
|
||||
type Gateway interface {
|
||||
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error)
|
||||
GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error)
|
||||
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
ChainPutObj(context.Context, blocks.Block) error
|
||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||
|
||||
@@ -449,6 +449,8 @@ type GatewayMethods struct {
|
||||
|
||||
ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) ``
|
||||
|
||||
GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) ``
|
||||
|
||||
GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) ``
|
||||
|
||||
MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) ``
|
||||
@@ -487,10 +489,14 @@ type GatewayMethods struct {
|
||||
|
||||
StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) ``
|
||||
|
||||
StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) ``
|
||||
|
||||
StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) ``
|
||||
|
||||
StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) ``
|
||||
|
||||
StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) ``
|
||||
|
||||
StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) ``
|
||||
|
||||
StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) ``
|
||||
@@ -2674,6 +2680,17 @@ func (s *GatewayStub) ChainReadObj(p0 context.Context, p1 cid.Cid) ([]byte, erro
|
||||
return *new([]byte), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) {
|
||||
if s.Internal.GasEstimateGasPremium == nil {
|
||||
return *new(types.BigInt), ErrNotSupported
|
||||
}
|
||||
return s.Internal.GasEstimateGasPremium(p0, p1, p2, p3, p4)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) GasEstimateGasPremium(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) {
|
||||
return *new(types.BigInt), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) GasEstimateMessageGas(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) {
|
||||
if s.Internal.GasEstimateMessageGas == nil {
|
||||
return nil, ErrNotSupported
|
||||
@@ -2883,6 +2900,17 @@ func (s *GatewayStub) StateMinerProvingDeadline(p0 context.Context, p1 address.A
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) {
|
||||
if s.Internal.StateMinerSectorCount == nil {
|
||||
return *new(api.MinerSectors), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StateMinerSectorCount(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) StateMinerSectorCount(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) {
|
||||
return *new(api.MinerSectors), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateNetworkName(p0 context.Context) (dtypes.NetworkName, error) {
|
||||
if s.Internal.StateNetworkName == nil {
|
||||
return *new(dtypes.NetworkName), ErrNotSupported
|
||||
@@ -2905,6 +2933,17 @@ func (s *GatewayStub) StateNetworkVersion(p0 context.Context, p1 types.TipSetKey
|
||||
return *new(abinetwork.Version), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) {
|
||||
if s.Internal.StateReplay == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.StateReplay(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) {
|
||||
if s.Internal.StateSearchMsg == nil {
|
||||
return nil, ErrNotSupported
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -93,7 +93,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
||||
}()
|
||||
|
||||
ctx = blockstore.WithHotView(ctx)
|
||||
makeVm := func(base cid.Cid, e abi.ChainEpoch, timestamp uint64) (vm.Interface, error) {
|
||||
makeVm := func(base cid.Cid, e abi.ChainEpoch, timestamp uint64) (vm.Executor, error) {
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: e,
|
||||
@@ -109,6 +109,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
||||
TipSetGetter: stmgr.TipSetGetterForTipset(sm.ChainStore(), ts),
|
||||
Tracing: vmTracing,
|
||||
ReturnEvents: sm.ChainStore().IsStoringEvents(),
|
||||
ExecutionLane: vm.ExecutionLanePriority,
|
||||
}
|
||||
|
||||
return sm.VMConstructor()(ctx, vmopt)
|
||||
@@ -116,7 +117,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
||||
|
||||
var cronGas int64
|
||||
|
||||
runCron := func(vmCron vm.Interface, epoch abi.ChainEpoch) error {
|
||||
runCron := func(vmCron vm.Executor, epoch abi.ChainEpoch) error {
|
||||
cronMsg := &types.Message{
|
||||
To: cron.Address,
|
||||
From: builtin.SystemActorAddr,
|
||||
@@ -169,13 +170,17 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
||||
|
||||
// run cron for null rounds if any
|
||||
if err = runCron(vmCron, i); err != nil {
|
||||
vmCron.Done()
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("running cron: %w", err)
|
||||
}
|
||||
|
||||
pstate, err = vmCron.Flush(ctx)
|
||||
if err != nil {
|
||||
vmCron.Done()
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("flushing cron vm: %w", err)
|
||||
}
|
||||
|
||||
vmCron.Done()
|
||||
}
|
||||
|
||||
// handle state forks
|
||||
@@ -191,10 +196,12 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
||||
cronGas = 0
|
||||
partDone = metrics.Timer(ctx, metrics.VMApplyMessages)
|
||||
|
||||
// TODO reorg the code to minimize the execution critical section
|
||||
vmi, err := makeVm(pstate, epoch, ts.MinTimestamp())
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
|
||||
}
|
||||
defer vmi.Done()
|
||||
|
||||
var (
|
||||
receipts []*types.MessageReceipt
|
||||
|
||||
@@ -496,6 +496,7 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, sys vm.Sysca
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create VM: %w", err)
|
||||
}
|
||||
defer vm.Done()
|
||||
|
||||
for mi, m := range template.Miners {
|
||||
for si, s := range m.Sectors {
|
||||
|
||||
@@ -88,7 +88,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
|
||||
return big.Zero(), nil
|
||||
}
|
||||
|
||||
newVM := func(base cid.Cid) (vm.Interface, error) {
|
||||
newVM := func(base cid.Cid) (vm.Executor, error) {
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: 0,
|
||||
@@ -108,6 +108,8 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("creating vm: %w", err)
|
||||
}
|
||||
// Note: genesisVm is mutated, so this has to happen in a deferred func; go horror show.
|
||||
defer func() { genesisVm.Done() }()
|
||||
|
||||
if len(miners) == 0 {
|
||||
return cid.Undef, xerrors.New("no genesis miners")
|
||||
@@ -338,6 +340,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
|
||||
return cid.Undef, xerrors.Errorf("flushing state tree: %w", err)
|
||||
}
|
||||
|
||||
genesisVm.Done()
|
||||
genesisVm, err = newVM(nh)
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("creating new vm: %w", err)
|
||||
@@ -410,6 +413,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
|
||||
return cid.Undef, xerrors.Errorf("flushing state tree: %w", err)
|
||||
}
|
||||
|
||||
genesisVm.Done()
|
||||
genesisVm, err = newVM(nh)
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("creating new vm: %w", err)
|
||||
@@ -517,6 +521,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
|
||||
return cid.Undef, xerrors.Errorf("flushing state tree: %w", err)
|
||||
}
|
||||
|
||||
genesisVm.Done()
|
||||
genesisVm, err = newVM(nh)
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("creating new vm: %w", err)
|
||||
|
||||
+20
-6
@@ -52,8 +52,8 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
||||
}
|
||||
|
||||
// CallWithGas calculates the state for a given tipset, and then applies the given message on top of that state.
|
||||
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) {
|
||||
return sm.callInternal(ctx, msg, priorMsgs, ts, cid.Undef, sm.GetNetworkVersion, true, true)
|
||||
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet, applyTsMessages bool) (*api.InvocResult, error) {
|
||||
return sm.callInternal(ctx, msg, priorMsgs, ts, cid.Undef, sm.GetNetworkVersion, true, applyTsMessages)
|
||||
}
|
||||
|
||||
// CallAtStateAndVersion allows you to specify a message to execute on the given stateCid and network version.
|
||||
@@ -117,12 +117,22 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
||||
if stateCid == cid.Undef {
|
||||
stateCid = ts.ParentState()
|
||||
}
|
||||
tsMsgs, err := sm.cs.MessagesForTipset(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to lookup messages for parent tipset: %w", err)
|
||||
}
|
||||
|
||||
if applyTsMessages {
|
||||
tsMsgs, err := sm.cs.MessagesForTipset(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to lookup messages for parent tipset: %w", err)
|
||||
}
|
||||
priorMsgs = append(tsMsgs, priorMsgs...)
|
||||
} else {
|
||||
var filteredTsMsgs []types.ChainMsg
|
||||
for _, tsMsg := range tsMsgs {
|
||||
//TODO we should technically be normalizing the filecoin address of from when we compare here
|
||||
if tsMsg.VMMessage().From == msg.VMMessage().From {
|
||||
filteredTsMsgs = append(filteredTsMsgs, tsMsg)
|
||||
}
|
||||
}
|
||||
priorMsgs = append(filteredTsMsgs, priorMsgs...)
|
||||
}
|
||||
|
||||
// Technically, the tipset we're passing in here should be ts+1, but that may not exist.
|
||||
@@ -159,6 +169,9 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||
}
|
||||
// Note: vmi is mutated, so this has to happen in a deferred func; go horror show.
|
||||
defer func() { vmi.Done() }()
|
||||
|
||||
for i, m := range priorMsgs {
|
||||
_, err = vmi.ApplyMessage(ctx, m)
|
||||
if err != nil {
|
||||
@@ -191,6 +204,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
||||
vmopt.BaseFee = big.Zero()
|
||||
vmopt.StateBase = stateCid
|
||||
|
||||
vmi.Done()
|
||||
vmi, err = sm.newVM(ctx, vmopt)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to set up estimation vm: %w", err)
|
||||
|
||||
@@ -128,10 +128,38 @@ func (sm *StateManager) ExecutionTraceWithMonitor(ctx context.Context, ts *types
|
||||
}
|
||||
|
||||
func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) {
|
||||
tsKey := ts.Key()
|
||||
|
||||
{
|
||||
// check if we have the trace for this tipset in the cache
|
||||
sm.execTraceCacheLock.Lock()
|
||||
defer sm.execTraceCacheLock.Unlock()
|
||||
if entry, ok := sm.execTraceCache.Get(tsKey); ok {
|
||||
// we have to make a deep copy since caller can modify the invocTrace
|
||||
return entry.postStateRoot, makeDeepCopy(entry.invocTrace), nil
|
||||
}
|
||||
}
|
||||
|
||||
var invocTrace []*api.InvocResult
|
||||
st, err := sm.ExecutionTraceWithMonitor(ctx, ts, &InvocationTracer{trace: &invocTrace})
|
||||
if err != nil {
|
||||
return cid.Undef, nil, err
|
||||
}
|
||||
|
||||
sm.execTraceCache.Add(tsKey, tipSetCacheEntry{st, makeDeepCopy(invocTrace)})
|
||||
|
||||
return st, invocTrace, nil
|
||||
}
|
||||
|
||||
func makeDeepCopy(invocTrace []*api.InvocResult) []*api.InvocResult {
|
||||
c := make([]*api.InvocResult, len(invocTrace))
|
||||
for i, ir := range invocTrace {
|
||||
if ir == nil {
|
||||
continue
|
||||
}
|
||||
tmp := *ir
|
||||
c[i] = &tmp
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
+20
-14
@@ -56,6 +56,12 @@ const testForkHeight = 40
|
||||
type testActor struct {
|
||||
}
|
||||
|
||||
type mockExecutor struct {
|
||||
vm.Interface
|
||||
}
|
||||
|
||||
func (*mockExecutor) Done() {}
|
||||
|
||||
// must use existing actor that an account is allowed to exec.
|
||||
func (testActor) Code() cid.Cid { return builtin0.PaymentChannelActorCodeID }
|
||||
func (testActor) State() cbor.Er { return new(testActorState) }
|
||||
@@ -178,13 +184,13 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
|
||||
inv.Register(actorstypes.Version0, nil, registry)
|
||||
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Executor, error) {
|
||||
nvm, err := vm.NewLegacyVM(ctx, vmopt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nvm.SetInvoker(inv)
|
||||
return nvm, nil
|
||||
return &mockExecutor{nvm}, nil
|
||||
})
|
||||
|
||||
cg.SetStateManager(sm)
|
||||
@@ -296,13 +302,13 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) {
|
||||
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
|
||||
inv.Register(actorstypes.Version0, nil, registry)
|
||||
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Executor, error) {
|
||||
nvm, err := vm.NewLegacyVM(ctx, vmopt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nvm.SetInvoker(inv)
|
||||
return nvm, nil
|
||||
return &mockExecutor{nvm}, nil
|
||||
})
|
||||
|
||||
cg.SetStateManager(sm)
|
||||
@@ -341,7 +347,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) {
|
||||
currentHeight := ts.TipSet.TipSet().Height()
|
||||
|
||||
// CallWithGas calls on top of the given tipset.
|
||||
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet())
|
||||
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet(), true)
|
||||
if parentHeight <= testForkHeight && currentHeight >= testForkHeight {
|
||||
// If I had a fork, or I _will_ have a fork, it should fail.
|
||||
require.Equal(t, ErrExpensiveFork, err)
|
||||
@@ -362,7 +368,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) {
|
||||
// Calls without a tipset should walk back to the last non-fork tipset.
|
||||
// We _verify_ that the migration wasn't run multiple times at the end of the
|
||||
// test.
|
||||
ret, err = sm.CallWithGas(ctx, m, nil, nil)
|
||||
ret, err = sm.CallWithGas(ctx, m, nil, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
|
||||
|
||||
@@ -518,13 +524,13 @@ func TestForkPreMigration(t *testing.T) {
|
||||
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
|
||||
inv.Register(actorstypes.Version0, nil, registry)
|
||||
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Executor, error) {
|
||||
nvm, err := vm.NewLegacyVM(ctx, vmopt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nvm.SetInvoker(inv)
|
||||
return nvm, nil
|
||||
return &mockExecutor{nvm}, nil
|
||||
})
|
||||
|
||||
cg.SetStateManager(sm)
|
||||
@@ -592,11 +598,11 @@ func TestDisablePreMigration(t *testing.T) {
|
||||
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
|
||||
inv.Register(actorstypes.Version0, nil, registry)
|
||||
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Executor, error) {
|
||||
nvm, err := vm.NewLegacyVM(ctx, vmopt)
|
||||
require.NoError(t, err)
|
||||
nvm.SetInvoker(inv)
|
||||
return nvm, nil
|
||||
return &mockExecutor{nvm}, nil
|
||||
})
|
||||
|
||||
cg.SetStateManager(sm)
|
||||
@@ -647,11 +653,11 @@ func TestMigrtionCache(t *testing.T) {
|
||||
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
|
||||
inv.Register(actorstypes.Version0, nil, registry)
|
||||
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Executor, error) {
|
||||
nvm, err := vm.NewLegacyVM(ctx, vmopt)
|
||||
require.NoError(t, err)
|
||||
nvm.SetInvoker(inv)
|
||||
return nvm, nil
|
||||
return &mockExecutor{nvm}, nil
|
||||
})
|
||||
|
||||
cg.SetStateManager(sm)
|
||||
@@ -691,11 +697,11 @@ func TestMigrtionCache(t *testing.T) {
|
||||
index.DummyMsgIndex,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Executor, error) {
|
||||
nvm, err := vm.NewLegacyVM(ctx, vmopt)
|
||||
require.NoError(t, err)
|
||||
nvm.SetInvoker(inv)
|
||||
return nvm, nil
|
||||
return &mockExecutor{nvm}, nil
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
+25
-7
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"github.com/ipfs/go-cid"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
@@ -39,6 +40,8 @@ import (
|
||||
const LookbackNoLimit = api.LookbackNoLimit
|
||||
const ReceiptAmtBitwidth = 3
|
||||
|
||||
const execTraceCacheSize = 16
|
||||
|
||||
var log = logging.Logger("statemgr")
|
||||
|
||||
type StateManagerAPI interface {
|
||||
@@ -125,19 +128,23 @@ type StateManager struct {
|
||||
compWait map[string]chan struct{}
|
||||
stlk sync.Mutex
|
||||
genesisMsigLk sync.Mutex
|
||||
newVM func(context.Context, *vm.VMOpts) (vm.Interface, error)
|
||||
newVM func(context.Context, *vm.VMOpts) (vm.Executor, error)
|
||||
Syscalls vm.SyscallBuilder
|
||||
preIgnitionVesting []msig0.State
|
||||
postIgnitionVesting []msig0.State
|
||||
postCalicoVesting []msig0.State
|
||||
|
||||
genesisPledge abi.TokenAmount
|
||||
genesisMarketFunds abi.TokenAmount
|
||||
genesisPledge abi.TokenAmount
|
||||
|
||||
tsExec Executor
|
||||
tsExecMonitor ExecMonitor
|
||||
beacon beacon.Schedule
|
||||
|
||||
// We keep a small cache for calls to ExecutionTrace which helps improve
|
||||
// performance for node operators like exchanges and block explorers
|
||||
execTraceCache *lru.ARCCache[types.TipSetKey, tipSetCacheEntry]
|
||||
execTraceCacheLock sync.Mutex
|
||||
|
||||
msgIndex index.MsgIndex
|
||||
}
|
||||
|
||||
@@ -147,6 +154,11 @@ type treeCache struct {
|
||||
tree *state.StateTree
|
||||
}
|
||||
|
||||
type tipSetCacheEntry struct {
|
||||
postStateRoot cid.Cid
|
||||
invocTrace []*api.InvocResult
|
||||
}
|
||||
|
||||
func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, beacon beacon.Schedule, metadataDs dstore.Batching, msgIndex index.MsgIndex) (*StateManager, error) {
|
||||
// If we have upgrades, make sure they're in-order and make sense.
|
||||
if err := us.Validate(); err != nil {
|
||||
@@ -186,6 +198,11 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder,
|
||||
}
|
||||
}
|
||||
|
||||
execTraceCache, err := lru.NewARC[types.TipSetKey, tipSetCacheEntry](execTraceCacheSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &StateManager{
|
||||
networkVersions: networkVersions,
|
||||
latestVersion: lastVersion,
|
||||
@@ -201,7 +218,8 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder,
|
||||
root: cid.Undef,
|
||||
tree: nil,
|
||||
},
|
||||
compWait: make(map[string]chan struct{}),
|
||||
compWait: make(map[string]chan struct{}),
|
||||
execTraceCache: execTraceCache,
|
||||
msgIndex: msgIndex,
|
||||
}, nil
|
||||
}
|
||||
@@ -439,12 +457,12 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) SetVMConstructor(nvm func(context.Context, *vm.VMOpts) (vm.Interface, error)) {
|
||||
func (sm *StateManager) SetVMConstructor(nvm func(context.Context, *vm.VMOpts) (vm.Executor, error)) {
|
||||
sm.newVM = nvm
|
||||
}
|
||||
|
||||
func (sm *StateManager) VMConstructor() func(context.Context, *vm.VMOpts) (vm.Interface, error) {
|
||||
return func(ctx context.Context, opts *vm.VMOpts) (vm.Interface, error) {
|
||||
func (sm *StateManager) VMConstructor() func(context.Context, *vm.VMOpts) (vm.Executor, error) {
|
||||
return func(ctx context.Context, opts *vm.VMOpts) (vm.Executor, error) {
|
||||
return sm.newVM(ctx, opts)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-12
@@ -51,17 +51,13 @@ func (sm *StateManager) setupGenesisVestingSchedule(ctx context.Context) error {
|
||||
return xerrors.Errorf("loading state tree: %w", err)
|
||||
}
|
||||
|
||||
gmf, err := getFilMarketLocked(ctx, sTree)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("setting up genesis market funds: %w", err)
|
||||
}
|
||||
|
||||
gp, err := getFilPowerLocked(ctx, sTree)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("setting up genesis pledge: %w", err)
|
||||
}
|
||||
|
||||
sm.genesisMarketFunds = gmf
|
||||
sm.genesisMsigLk.Lock()
|
||||
defer sm.genesisMsigLk.Unlock()
|
||||
sm.genesisPledge = gp
|
||||
|
||||
totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount)
|
||||
@@ -128,6 +124,8 @@ func (sm *StateManager) setupPostIgnitionVesting(ctx context.Context) error {
|
||||
totalsByEpoch[sixYears] = big.NewInt(100_000_000)
|
||||
totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000))
|
||||
|
||||
sm.genesisMsigLk.Lock()
|
||||
defer sm.genesisMsigLk.Unlock()
|
||||
sm.postIgnitionVesting = make([]msig0.State, 0, len(totalsByEpoch))
|
||||
for k, v := range totalsByEpoch {
|
||||
ns := msig0.State{
|
||||
@@ -178,6 +176,9 @@ func (sm *StateManager) setupPostCalicoVesting(ctx context.Context) error {
|
||||
totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000))
|
||||
totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(9_805_053))
|
||||
|
||||
sm.genesisMsigLk.Lock()
|
||||
defer sm.genesisMsigLk.Unlock()
|
||||
|
||||
sm.postCalicoVesting = make([]msig0.State, 0, len(totalsByEpoch))
|
||||
for k, v := range totalsByEpoch {
|
||||
ns := msig0.State{
|
||||
@@ -198,21 +199,20 @@ func (sm *StateManager) setupPostCalicoVesting(ctx context.Context) error {
|
||||
func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch) (abi.TokenAmount, error) {
|
||||
vf := big.Zero()
|
||||
|
||||
sm.genesisMsigLk.Lock()
|
||||
defer sm.genesisMsigLk.Unlock()
|
||||
|
||||
// TODO: combine all this?
|
||||
if sm.preIgnitionVesting == nil || sm.genesisPledge.IsZero() || sm.genesisMarketFunds.IsZero() {
|
||||
if sm.preIgnitionVesting == nil || sm.genesisPledge.IsZero() {
|
||||
err := sm.setupGenesisVestingSchedule(ctx)
|
||||
if err != nil {
|
||||
return vf, xerrors.Errorf("failed to setup pre-ignition vesting schedule: %w", err)
|
||||
}
|
||||
|
||||
}
|
||||
if sm.postIgnitionVesting == nil {
|
||||
err := sm.setupPostIgnitionVesting(ctx)
|
||||
if err != nil {
|
||||
return vf, xerrors.Errorf("failed to setup post-ignition vesting schedule: %w", err)
|
||||
}
|
||||
|
||||
}
|
||||
if sm.postCalicoVesting == nil {
|
||||
err := sm.setupPostCalicoVesting(ctx)
|
||||
@@ -246,8 +246,6 @@ func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch)
|
||||
if height <= build.UpgradeAssemblyHeight {
|
||||
// continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
|
||||
vf = big.Add(vf, sm.genesisPledge)
|
||||
// continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
|
||||
vf = big.Add(vf, sm.genesisMarketFunds)
|
||||
}
|
||||
|
||||
return vf, nil
|
||||
|
||||
@@ -106,6 +106,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
||||
if err != nil {
|
||||
return cid.Undef, nil, err
|
||||
}
|
||||
defer vmi.Done()
|
||||
|
||||
for i, msg := range msgs {
|
||||
// TODO: Use the signed message length for secp messages
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/tag"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultAvailableExecutionLanes is the number of available execution lanes; it is the bound of
|
||||
// concurrent active executions.
|
||||
// This is the default value in filecoin-ffi
|
||||
DefaultAvailableExecutionLanes = 4
|
||||
// DefaultPriorityExecutionLanes is the number of reserved execution lanes for priority computations.
|
||||
// This is purely userspace, but we believe it is a reasonable default, even with more available
|
||||
// lanes.
|
||||
DefaultPriorityExecutionLanes = 2
|
||||
)
|
||||
|
||||
var ErrExecutorDone = errors.New("executor has been released")
|
||||
|
||||
// the execution environment; see below for definition, methods, and initilization
|
||||
var execution *executionEnv
|
||||
|
||||
// implementation of vm executor with simple sanity check preventing use after free.
|
||||
type vmExecutor struct {
|
||||
lk sync.RWMutex
|
||||
vmi Interface
|
||||
token *executionToken
|
||||
done bool
|
||||
}
|
||||
|
||||
var _ Executor = (*vmExecutor)(nil)
|
||||
|
||||
func newVMExecutor(vmi Interface, token *executionToken) Executor {
|
||||
return &vmExecutor{vmi: vmi, token: token}
|
||||
}
|
||||
|
||||
func (e *vmExecutor) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) {
|
||||
e.lk.RLock()
|
||||
defer e.lk.RUnlock()
|
||||
|
||||
if e.done {
|
||||
return nil, ErrExecutorDone
|
||||
}
|
||||
|
||||
return e.vmi.ApplyMessage(ctx, cmsg)
|
||||
}
|
||||
|
||||
func (e *vmExecutor) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) {
|
||||
e.lk.RLock()
|
||||
defer e.lk.RUnlock()
|
||||
|
||||
if e.done {
|
||||
return nil, ErrExecutorDone
|
||||
}
|
||||
|
||||
return e.vmi.ApplyImplicitMessage(ctx, msg)
|
||||
}
|
||||
|
||||
func (e *vmExecutor) Flush(ctx context.Context) (cid.Cid, error) {
|
||||
e.lk.RLock()
|
||||
defer e.lk.RUnlock()
|
||||
|
||||
if e.done {
|
||||
return cid.Undef, ErrExecutorDone
|
||||
}
|
||||
|
||||
return e.vmi.Flush(ctx)
|
||||
}
|
||||
|
||||
func (e *vmExecutor) Done() {
|
||||
e.lk.Lock()
|
||||
defer e.lk.Unlock()
|
||||
|
||||
if !e.done {
|
||||
e.token.Done()
|
||||
e.token = nil
|
||||
e.done = true
|
||||
}
|
||||
}
|
||||
|
||||
type executionToken struct {
|
||||
lane ExecutionLane
|
||||
reserved int
|
||||
}
|
||||
|
||||
func (token *executionToken) Done() {
|
||||
execution.putToken(token)
|
||||
}
|
||||
|
||||
type executionEnv struct {
|
||||
mx *sync.Mutex
|
||||
cond *sync.Cond
|
||||
|
||||
// available executors
|
||||
available int
|
||||
// reserved executors
|
||||
reserved int
|
||||
}
|
||||
|
||||
func (e *executionEnv) getToken(lane ExecutionLane) *executionToken {
|
||||
metricsUp(metrics.VMExecutionWaiting, lane)
|
||||
defer metricsDown(metrics.VMExecutionWaiting, lane)
|
||||
|
||||
e.mx.Lock()
|
||||
defer e.mx.Unlock()
|
||||
|
||||
switch lane {
|
||||
case ExecutionLaneDefault:
|
||||
for e.available <= e.reserved {
|
||||
e.cond.Wait()
|
||||
}
|
||||
|
||||
e.available--
|
||||
|
||||
metricsUp(metrics.VMExecutionRunning, lane)
|
||||
return &executionToken{lane: lane, reserved: 0}
|
||||
|
||||
case ExecutionLanePriority:
|
||||
for e.available == 0 {
|
||||
e.cond.Wait()
|
||||
}
|
||||
|
||||
e.available--
|
||||
|
||||
reserving := 0
|
||||
if e.reserved > 0 {
|
||||
e.reserved--
|
||||
reserving = 1
|
||||
}
|
||||
|
||||
metricsUp(metrics.VMExecutionRunning, lane)
|
||||
return &executionToken{lane: lane, reserved: reserving}
|
||||
|
||||
default:
|
||||
// already checked at interface boundary in NewVM, so this is appropriate
|
||||
panic("bogus execution lane")
|
||||
}
|
||||
}
|
||||
|
||||
func (e *executionEnv) putToken(token *executionToken) {
|
||||
e.mx.Lock()
|
||||
defer e.mx.Unlock()
|
||||
|
||||
e.available++
|
||||
e.reserved += token.reserved
|
||||
|
||||
e.cond.Broadcast()
|
||||
|
||||
metricsDown(metrics.VMExecutionRunning, token.lane)
|
||||
}
|
||||
|
||||
func metricsUp(metric *stats.Int64Measure, lane ExecutionLane) {
|
||||
metricsAdjust(metric, lane, 1)
|
||||
}
|
||||
|
||||
func metricsDown(metric *stats.Int64Measure, lane ExecutionLane) {
|
||||
metricsAdjust(metric, lane, -1)
|
||||
}
|
||||
|
||||
func metricsAdjust(metric *stats.Int64Measure, lane ExecutionLane, delta int) {
|
||||
laneName := "default"
|
||||
if lane > ExecutionLaneDefault {
|
||||
laneName = "priority"
|
||||
}
|
||||
|
||||
ctx, _ := tag.New(
|
||||
context.Background(),
|
||||
tag.Upsert(metrics.ExecutionLane, laneName),
|
||||
)
|
||||
stats.Record(ctx, metric.M(int64(delta)))
|
||||
}
|
||||
|
||||
func init() {
|
||||
var available, priority int
|
||||
var err error
|
||||
|
||||
concurrency := os.Getenv("LOTUS_FVM_CONCURRENCY")
|
||||
if concurrency == "" {
|
||||
available = DefaultAvailableExecutionLanes
|
||||
} else {
|
||||
available, err = strconv.Atoi(concurrency)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
reserved := os.Getenv("LOTUS_FVM_CONCURRENCY_RESERVED")
|
||||
if reserved == "" {
|
||||
priority = DefaultPriorityExecutionLanes
|
||||
} else {
|
||||
priority, err = strconv.Atoi(reserved)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// some sanity checks
|
||||
if available < 2 {
|
||||
panic("insufficient execution concurrency")
|
||||
}
|
||||
|
||||
if priority > available-1 {
|
||||
panic("insufficient default execution concurrency")
|
||||
}
|
||||
|
||||
mx := &sync.Mutex{}
|
||||
cond := sync.NewCond(mx)
|
||||
|
||||
execution = &executionEnv{
|
||||
mx: mx,
|
||||
cond: cond,
|
||||
available: available,
|
||||
reserved: priority,
|
||||
}
|
||||
}
|
||||
@@ -250,6 +250,8 @@ type VMOpts struct {
|
||||
Tracing bool
|
||||
// ReturnEvents decodes and returns emitted events.
|
||||
ReturnEvents bool
|
||||
// ExecutionLane specifies the execution priority of the created vm
|
||||
ExecutionLane ExecutionLane
|
||||
}
|
||||
|
||||
func NewLegacyVM(ctx context.Context, opts *VMOpts) (*LegacyVM, error) {
|
||||
|
||||
+40
-1
@@ -2,6 +2,7 @@ package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
@@ -17,6 +18,15 @@ var (
|
||||
StatApplied uint64
|
||||
)
|
||||
|
||||
type ExecutionLane int
|
||||
|
||||
const (
|
||||
// ExecutionLaneDefault signifies a default, non prioritized execution lane.
|
||||
ExecutionLaneDefault ExecutionLane = iota
|
||||
// ExecutionLanePriority signifies a prioritized execution lane with reserved resources.
|
||||
ExecutionLanePriority
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
// Applies the given message onto the VM's current state, returning the result of the execution
|
||||
ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error)
|
||||
@@ -27,13 +37,24 @@ type Interface interface {
|
||||
Flush(ctx context.Context) (cid.Cid, error)
|
||||
}
|
||||
|
||||
// Executor is the general vm execution interface, which is prioritized according to execution lanes.
|
||||
// User must call Done when it is done with this executor to release resource holds by the execution
|
||||
// environment
|
||||
type Executor interface {
|
||||
Interface
|
||||
|
||||
// Done must be called when done with the executor to release resource holds.
|
||||
// It is an error to invoke Interface methods after Done has been called.
|
||||
Done()
|
||||
}
|
||||
|
||||
// WARNING: You will not affect your node's execution by misusing this feature, but you will confuse yourself thoroughly!
|
||||
// An envvar that allows the user to specify debug actors bundles to be used by the FVM
|
||||
// alongside regular execution. This is basically only to be used to print out specific logging information.
|
||||
// Message failures, unexpected terminations,gas costs, etc. should all be ignored.
|
||||
var useFvmDebug = os.Getenv("LOTUS_FVM_DEVELOPER_DEBUG") == "1"
|
||||
|
||||
func NewVM(ctx context.Context, opts *VMOpts) (Interface, error) {
|
||||
func newVM(ctx context.Context, opts *VMOpts) (Interface, error) {
|
||||
if opts.NetworkVersion >= network.Version16 {
|
||||
if useFvmDebug {
|
||||
return NewDualExecutionFVM(ctx, opts)
|
||||
@@ -43,3 +64,21 @@ func NewVM(ctx context.Context, opts *VMOpts) (Interface, error) {
|
||||
|
||||
return NewLegacyVM(ctx, opts)
|
||||
}
|
||||
|
||||
func NewVM(ctx context.Context, opts *VMOpts) (Executor, error) {
|
||||
switch opts.ExecutionLane {
|
||||
case ExecutionLaneDefault, ExecutionLanePriority:
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid execution lane: %d", opts.ExecutionLane)
|
||||
}
|
||||
|
||||
token := execution.getToken(opts.ExecutionLane)
|
||||
|
||||
vmi, err := newVM(ctx, opts)
|
||||
if err != nil {
|
||||
token.Done()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newVMExecutor(vmi, token), nil
|
||||
}
|
||||
|
||||
@@ -325,14 +325,12 @@ func handleMiningInfo(ctx context.Context, cctx *cli.Context, fullapi v1api.Full
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
fmt.Println()
|
||||
|
||||
ws, err := nodeApi.WorkerStats(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting worker stats: %w", err)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
ws, err := nodeApi.WorkerStats(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: getting worker stats: %s\n", err)
|
||||
} else {
|
||||
workersByType := map[string]int{
|
||||
sealtasks.WorkerSealing: 0,
|
||||
sealtasks.WorkerWindowPoSt: 0,
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
)
|
||||
|
||||
var chainwatchCmd = &cli.Command{
|
||||
Name: "chainwatch",
|
||||
Usage: "lotus chainwatch",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "db",
|
||||
EnvVars: []string{"CHAINWATCH_DB"},
|
||||
Value: "./chainwatch.db",
|
||||
},
|
||||
},
|
||||
Subcommands: []*cli.Command{
|
||||
chainwatchRunCmd,
|
||||
chainwatchDotCmd,
|
||||
},
|
||||
}
|
||||
|
||||
var chainwatchDotCmd = &cli.Command{
|
||||
Name: "dot",
|
||||
Usage: "generate dot graphs",
|
||||
ArgsUsage: "<minHeight> <toseeHeight>",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
st, err := cwOpenStorage(cctx.String("db"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
minH, err := strconv.ParseInt(cctx.Args().Get(0), 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tosee, err := strconv.ParseInt(cctx.Args().Get(1), 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
maxH := minH + tosee
|
||||
|
||||
res, err := st.db.Query(`select block, parent, b.miner, b.height, p.height from block_parents
|
||||
inner join blocks b on block_parents.block = b.cid
|
||||
inner join blocks p on block_parents.parent = p.cid
|
||||
where b.height > ? and b.height < ?`, minH, maxH)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("digraph D {")
|
||||
|
||||
for res.Next() {
|
||||
var block, parent, miner string
|
||||
var height, ph uint64
|
||||
if err := res.Scan(&block, &parent, &miner, &height, &ph); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bc, err := cid.Parse(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
has := st.hasBlock(bc)
|
||||
|
||||
col := crc32.Checksum([]byte(miner), crc32.MakeTable(crc32.Castagnoli))&0xc0c0c0c0 + 0x30303030
|
||||
|
||||
hasstr := ""
|
||||
if !has {
|
||||
//col = 0xffffffff
|
||||
hasstr = " UNSYNCED"
|
||||
}
|
||||
|
||||
nulls := height - ph - 1
|
||||
for i := uint64(0); i < nulls; i++ {
|
||||
name := block + "NP" + fmt.Sprint(i)
|
||||
|
||||
fmt.Printf("%s [label = \"NULL:%d\", fillcolor = \"#ffddff\", style=filled, forcelabels=true]\n%s -> %s\n",
|
||||
name, height-nulls+i, name, parent)
|
||||
|
||||
parent = name
|
||||
}
|
||||
|
||||
fmt.Printf("%s [label = \"%s:%d%s\", fillcolor = \"#%06x\", style=filled, forcelabels=true]\n%s -> %s\n", block, miner, height, hasstr, col, block, parent)
|
||||
}
|
||||
if res.Err() != nil {
|
||||
return res.Err()
|
||||
}
|
||||
|
||||
fmt.Println("}")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var chainwatchRunCmd = &cli.Command{
|
||||
Name: "run",
|
||||
Usage: "Start lotus chainwatch",
|
||||
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := cliutil.GetFullNodeAPIV1(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := cliutil.ReqContext(cctx)
|
||||
|
||||
v, err := api.Version(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Remote version: %s", v.Version)
|
||||
|
||||
st, err := cwOpenStorage(cctx.String("db")) // todo flag
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer st.close() // nolint:errcheck
|
||||
|
||||
cwRunSyncer(ctx, api, st)
|
||||
go cwSubBlocks(ctx, api, st)
|
||||
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func cwSubBlocks(ctx context.Context, api api.FullNode, st *cwStorage) {
|
||||
sub, err := api.SyncIncomingBlocks(ctx)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for bh := range sub {
|
||||
err := st.storeHeaders(map[cid.Cid]*types.BlockHeader{
|
||||
bh.Cid(): bh,
|
||||
}, false)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cwRunSyncer(ctx context.Context, api api.FullNode, st *cwStorage) {
|
||||
notifs, err := api.ChainNotify(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go func() {
|
||||
for notif := range notifs {
|
||||
for _, change := range notif {
|
||||
switch change.Type {
|
||||
case store.HCCurrent:
|
||||
fallthrough
|
||||
case store.HCApply:
|
||||
syncHead(ctx, api, st, change.Val)
|
||||
case store.HCRevert:
|
||||
log.Warnf("revert todo")
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func syncHead(ctx context.Context, api api.FullNode, st *cwStorage, ts *types.TipSet) {
|
||||
log.Infof("Getting headers / actors")
|
||||
|
||||
toSync := map[cid.Cid]*types.BlockHeader{}
|
||||
toVisit := list.New()
|
||||
|
||||
for _, header := range ts.Blocks() {
|
||||
toVisit.PushBack(header)
|
||||
}
|
||||
|
||||
for toVisit.Len() > 0 {
|
||||
bh := toVisit.Remove(toVisit.Back()).(*types.BlockHeader)
|
||||
|
||||
if _, seen := toSync[bh.Cid()]; seen || st.hasBlock(bh.Cid()) {
|
||||
continue
|
||||
}
|
||||
|
||||
toSync[bh.Cid()] = bh
|
||||
|
||||
if len(toSync)%500 == 10 {
|
||||
log.Infof("todo: (%d) %s", len(toSync), bh.Cid())
|
||||
}
|
||||
|
||||
if len(bh.Parents) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if bh.Height <= 530000 {
|
||||
continue
|
||||
}
|
||||
|
||||
pts, err := api.ChainGetTipSet(ctx, types.NewTipSetKey(bh.Parents...))
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, header := range pts.Blocks() {
|
||||
toVisit.PushBack(header)
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("Syncing %d blocks", len(toSync))
|
||||
|
||||
log.Infof("Persisting headers")
|
||||
if err := st.storeHeaders(toSync, true); err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("Sync done")
|
||||
}
|
||||
|
||||
type cwStorage struct {
|
||||
db *sql.DB
|
||||
|
||||
headerLk sync.Mutex
|
||||
}
|
||||
|
||||
func cwOpenStorage(dbSource string) (*cwStorage, error) {
|
||||
db, err := sql.Open("sqlite3", dbSource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st := &cwStorage{db: db}
|
||||
|
||||
return st, st.setup()
|
||||
}
|
||||
|
||||
func (st *cwStorage) setup() error {
|
||||
tx, err := st.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.Exec(`
|
||||
create table if not exists blocks
|
||||
(
|
||||
cid text not null
|
||||
constraint blocks_pk
|
||||
primary key,
|
||||
parentWeight numeric not null,
|
||||
parentStateRoot text not null,
|
||||
height int not null,
|
||||
miner text not null
|
||||
constraint blocks_id_address_map_miner_fk
|
||||
references id_address_map (address),
|
||||
timestamp int not null,
|
||||
vrfproof blob
|
||||
);
|
||||
|
||||
create unique index if not exists block_cid_uindex
|
||||
on blocks (cid);
|
||||
|
||||
create table if not exists blocks_synced
|
||||
(
|
||||
cid text not null
|
||||
constraint blocks_synced_pk
|
||||
primary key
|
||||
constraint blocks_synced_blocks_cid_fk
|
||||
references blocks,
|
||||
add_ts int not null
|
||||
);
|
||||
|
||||
create unique index if not exists blocks_synced_cid_uindex
|
||||
on blocks_synced (cid);
|
||||
|
||||
create table if not exists block_parents
|
||||
(
|
||||
block text not null
|
||||
constraint block_parents_blocks_cid_fk
|
||||
references blocks,
|
||||
parent text not null
|
||||
constraint block_parents_blocks_cid_fk_2
|
||||
references blocks
|
||||
);
|
||||
|
||||
create unique index if not exists block_parents_block_parent_uindex
|
||||
on block_parents (block, parent);
|
||||
|
||||
create unique index if not exists blocks_cid_uindex
|
||||
on blocks (cid);
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (st *cwStorage) hasBlock(bh cid.Cid) bool {
|
||||
var exitsts bool
|
||||
err := st.db.QueryRow(`select exists (select 1 FROM blocks_synced where cid=?)`, bh.String()).Scan(&exitsts)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return false
|
||||
}
|
||||
return exitsts
|
||||
}
|
||||
|
||||
func (st *cwStorage) storeHeaders(bhs map[cid.Cid]*types.BlockHeader, sync bool) error {
|
||||
st.headerLk.Lock()
|
||||
defer st.headerLk.Unlock()
|
||||
|
||||
tx, err := st.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(`insert into blocks (cid, parentWeight, parentStateRoot, height, miner, "timestamp", vrfproof) values (?, ?, ?, ?, ?, ?, ?) on conflict do nothing`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt.Close() // nolint:errcheck
|
||||
for _, bh := range bhs {
|
||||
if _, err := stmt.Exec(bh.Cid().String(),
|
||||
bh.ParentWeight.String(),
|
||||
bh.ParentStateRoot.String(),
|
||||
bh.Height,
|
||||
bh.Miner.String(),
|
||||
bh.Timestamp,
|
||||
bh.Ticket.VRFProof,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
stmt2, err := tx.Prepare(`insert into block_parents (block, parent) values (?, ?) on conflict do nothing`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt2.Close() // nolint:errcheck
|
||||
for _, bh := range bhs {
|
||||
for _, parent := range bh.Parents {
|
||||
if _, err := stmt2.Exec(bh.Cid().String(), parent.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sync {
|
||||
stmt, err := tx.Prepare(`insert into blocks_synced (cid, add_ts) values (?, ?) on conflict do nothing`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt.Close() // nolint:errcheck
|
||||
now := time.Now().Unix()
|
||||
|
||||
for _, bh := range bhs {
|
||||
if _, err := stmt.Exec(bh.Cid().String(), now); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (st *cwStorage) close() error {
|
||||
return st.db.Close()
|
||||
}
|
||||
@@ -241,7 +241,7 @@ var replayOfflineCmd = &cli.Command{
|
||||
}
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', tabwriter.AlignRight)
|
||||
res, err := sm.CallWithGas(ctx, msg, []types.ChainMsg{}, executionTs)
|
||||
res, err := sm.CallWithGas(ctx, msg, []types.ChainMsg{}, executionTs, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ func main() {
|
||||
base32Cmd,
|
||||
base16Cmd,
|
||||
bitFieldCmd,
|
||||
chainwatchCmd,
|
||||
cronWcCmd,
|
||||
frozenMinersCmd,
|
||||
dealLabelCmd,
|
||||
|
||||
@@ -158,7 +158,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params
|
||||
results: []*vm.ApplyRet{},
|
||||
}
|
||||
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
|
||||
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Executor, error) {
|
||||
vmopt.CircSupplyCalc = func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) {
|
||||
return big.Zero(), nil
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ const (
|
||||
// TargetAPI defines the API methods that the Node depends on
|
||||
// (to make it easy to mock for tests)
|
||||
type TargetAPI interface {
|
||||
GasEstimateGasPremium(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error)
|
||||
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error)
|
||||
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error)
|
||||
Version(context.Context) (api.APIVersion, error)
|
||||
ChainGetParentMessages(context.Context, cid.Cid) ([]api.Message, error)
|
||||
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
|
||||
|
||||
@@ -23,6 +23,36 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
func (gw *Node) StateReplay(ctx context.Context, tsk types.TipSetKey, c cid.Cid) (*api.InvocResult, error) {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gw.target.StateReplay(ctx, tsk, c)
|
||||
}
|
||||
|
||||
func (gw *Node) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64, sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error) {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return types.BigInt{}, err
|
||||
}
|
||||
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return types.BigInt{}, err
|
||||
}
|
||||
return gw.target.GasEstimateGasPremium(ctx, nblocksincl, sender, gaslimit, tsk)
|
||||
}
|
||||
|
||||
func (gw *Node) StateMinerSectorCount(ctx context.Context, m address.Address, tsk types.TipSetKey) (api.MinerSectors, error) {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return api.MinerSectors{}, err
|
||||
}
|
||||
if err := gw.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return api.MinerSectors{}, err
|
||||
}
|
||||
return gw.target.StateMinerSectorCount(ctx, m, tsk)
|
||||
}
|
||||
|
||||
func (gw *Node) Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) {
|
||||
return build.OpenRPCDiscoverJSON_Gateway(), nil
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ require (
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab
|
||||
github.com/ipfs/bbloom v0.0.4
|
||||
github.com/ipfs/go-blockservice v0.5.0
|
||||
github.com/ipfs/go-cid v0.3.2
|
||||
github.com/ipfs/go-cid v0.4.0
|
||||
github.com/ipfs/go-cidutil v0.1.0
|
||||
github.com/ipfs/go-datastore v0.6.0
|
||||
github.com/ipfs/go-ds-badger2 v0.1.3
|
||||
@@ -97,7 +97,7 @@ require (
|
||||
github.com/ipfs/go-ipfs-util v0.0.2
|
||||
github.com/ipfs/go-ipld-cbor v0.0.6
|
||||
github.com/ipfs/go-ipld-format v0.4.0
|
||||
github.com/ipfs/go-libipfs v0.5.0
|
||||
github.com/ipfs/go-libipfs v0.7.0
|
||||
github.com/ipfs/go-log/v2 v2.5.1
|
||||
github.com/ipfs/go-merkledag v0.9.0
|
||||
github.com/ipfs/go-metrics-interface v0.0.1
|
||||
@@ -244,7 +244,7 @@ require (
|
||||
github.com/ipfs/go-ipld-legacy v0.1.1 // indirect
|
||||
github.com/ipfs/go-ipns v0.3.0 // indirect
|
||||
github.com/ipfs/go-log v1.0.5 // indirect
|
||||
github.com/ipfs/go-path v0.3.0 // indirect
|
||||
github.com/ipfs/go-path v0.3.1 // indirect
|
||||
github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
|
||||
github.com/ipfs/go-verifcid v0.0.2 // indirect
|
||||
github.com/ipld/go-ipld-adl-hamt v0.0.0-20220616142416-9004dbd839e0 // indirect
|
||||
|
||||
@@ -698,8 +698,8 @@ github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqg
|
||||
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
|
||||
github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o=
|
||||
github.com/ipfs/go-cid v0.2.0/go.mod h1:P+HXFDF4CVhaVayiEb4wkAy7zBHxBwsJyt0Y5U6MLro=
|
||||
github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc=
|
||||
github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw=
|
||||
github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA=
|
||||
github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
|
||||
github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q=
|
||||
github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
|
||||
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
|
||||
@@ -731,7 +731,6 @@ github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUN
|
||||
github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q=
|
||||
github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ=
|
||||
github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE=
|
||||
github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo=
|
||||
github.com/ipfs/go-filestore v1.2.0 h1:O2wg7wdibwxkEDcl7xkuQsPvJFRBVgVSsOJ/GP6z3yU=
|
||||
github.com/ipfs/go-filestore v1.2.0/go.mod h1:HLJrCxRXquTeEEpde4lTLMaE/MYJZD7WHLkp9z6+FF8=
|
||||
github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM=
|
||||
@@ -805,8 +804,8 @@ github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2
|
||||
github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg=
|
||||
github.com/ipfs/go-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A=
|
||||
github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24=
|
||||
github.com/ipfs/go-libipfs v0.5.0 h1:gtvzeoTdUHPUN4B5izzyBS3Cxtpvi+l7hd2mmjN+teM=
|
||||
github.com/ipfs/go-libipfs v0.5.0/go.mod h1:iZ9QyhzNr3AkxRXrbQYb//rv7iLyvZJX0GNuc3lJDiQ=
|
||||
github.com/ipfs/go-libipfs v0.7.0 h1:Mi54WJTODaOL2/ZSm5loi3SwI3jI2OuFWUrQIkJ5cpM=
|
||||
github.com/ipfs/go-libipfs v0.7.0/go.mod h1:KsIf/03CqhICzyRGyGo68tooiBE2iFbI/rXW7FhAYr0=
|
||||
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
|
||||
github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA=
|
||||
github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I=
|
||||
@@ -838,17 +837,15 @@ github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fG
|
||||
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
|
||||
github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s=
|
||||
github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks=
|
||||
github.com/ipfs/go-path v0.3.0 h1:tkjga3MtpXyM5v+3EbRvOHEoo+frwi4oumw5K+KYWyA=
|
||||
github.com/ipfs/go-path v0.3.0/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I=
|
||||
github.com/ipfs/go-path v0.3.1 h1:wkeaCWE/NTuuPGlEkLTsED5UkzfKYZpxaFFPgk8ZVLE=
|
||||
github.com/ipfs/go-path v0.3.1/go.mod h1:eNLsxJEEMxn/CDzUJ6wuNl+6No6tEUhOZcPKsZsYX0E=
|
||||
github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U=
|
||||
github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU=
|
||||
github.com/ipfs/go-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg=
|
||||
github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU=
|
||||
github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k=
|
||||
github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw=
|
||||
github.com/ipfs/go-unixfs v0.4.3 h1:EdDc1sNZNFDUlo4UrVAvvAofVI5EwTnKu8Nv8mgXkWQ=
|
||||
github.com/ipfs/go-unixfs v0.4.3/go.mod h1:TSG7G1UuT+l4pNj91raXAPkX0BhJi3jST1FDTfQ5QyM=
|
||||
github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s=
|
||||
github.com/ipfs/go-unixfsnode v1.5.2 h1:CvsiTt58W2uR5dD8bqQv+aAY0c1qolmXmSyNbPHYiew=
|
||||
github.com/ipfs/go-unixfsnode v1.5.2/go.mod h1:NlOebRwYx8lMCNMdhAhEspYPBD3obp7TE0LvBqHY+ks=
|
||||
github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0=
|
||||
|
||||
@@ -58,6 +58,9 @@ var (
|
||||
ProtocolID, _ = tag.NewKey("proto")
|
||||
Direction, _ = tag.NewKey("direction")
|
||||
UseFD, _ = tag.NewKey("use_fd")
|
||||
|
||||
// vm execution
|
||||
ExecutionLane, _ = tag.NewKey("lane")
|
||||
)
|
||||
|
||||
// Measures
|
||||
@@ -121,6 +124,8 @@ var (
|
||||
VMApplyFlush = stats.Float64("vm/applyblocks_flush", "Time spent flushing vm state", stats.UnitMilliseconds)
|
||||
VMSends = stats.Int64("vm/sends", "Counter for sends processed by the VM", stats.UnitDimensionless)
|
||||
VMApplied = stats.Int64("vm/applied", "Counter for messages (including internal messages) processed by the VM", stats.UnitDimensionless)
|
||||
VMExecutionWaiting = stats.Int64("vm/execution_waiting", "Counter for VM executions waiting to be assigned to a lane", stats.UnitDimensionless)
|
||||
VMExecutionRunning = stats.Int64("vm/execution_running", "Counter for running VM executions", stats.UnitDimensionless)
|
||||
|
||||
// miner
|
||||
WorkerCallsStarted = stats.Int64("sealing/worker_calls_started", "Counter of started worker tasks", stats.UnitDimensionless)
|
||||
@@ -363,6 +368,16 @@ var (
|
||||
Measure: VMApplied,
|
||||
Aggregation: view.LastValue(),
|
||||
}
|
||||
VMExecutionWaitingView = &view.View{
|
||||
Measure: VMExecutionWaiting,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{ExecutionLane},
|
||||
}
|
||||
VMExecutionRunningView = &view.View{
|
||||
Measure: VMExecutionRunning,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{ExecutionLane},
|
||||
}
|
||||
|
||||
// miner
|
||||
WorkerCallsStartedView = &view.View{
|
||||
|
||||
+13
-2
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
@@ -888,9 +889,14 @@ func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message, tsk ty
|
||||
return nil, xerrors.Errorf("cannot get tipset: %w", err)
|
||||
}
|
||||
|
||||
applyTsMessages := true
|
||||
if os.Getenv("LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS") == "1" {
|
||||
applyTsMessages = false
|
||||
}
|
||||
|
||||
// Try calling until we find a height with no migration.
|
||||
for {
|
||||
res, err = a.StateManager.CallWithGas(ctx, msg, []types.ChainMsg{}, ts)
|
||||
res, err = a.StateManager.CallWithGas(ctx, msg, []types.ChainMsg{}, ts, applyTsMessages)
|
||||
if err != stmgr.ErrExpensiveFork {
|
||||
break
|
||||
}
|
||||
@@ -959,10 +965,15 @@ func gasSearch(
|
||||
high := msg.GasLimit
|
||||
low := msg.GasLimit
|
||||
|
||||
applyTsMessages := true
|
||||
if os.Getenv("LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS") == "1" {
|
||||
applyTsMessages = false
|
||||
}
|
||||
|
||||
canSucceed := func(limit int64) (bool, error) {
|
||||
msg.GasLimit = limit
|
||||
|
||||
res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts, applyTsMessages)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
}
|
||||
|
||||
+7
-13
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
@@ -276,10 +277,15 @@ func gasEstimateCallWithGas(
|
||||
priorMsgs = append(priorMsgs, m)
|
||||
}
|
||||
|
||||
applyTsMessages := true
|
||||
if os.Getenv("LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS") == "1" {
|
||||
applyTsMessages = false
|
||||
}
|
||||
|
||||
// Try calling until we find a height with no migration.
|
||||
var res *api.InvocResult
|
||||
for {
|
||||
res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts, applyTsMessages)
|
||||
if err != stmgr.ErrExpensiveFork {
|
||||
break
|
||||
}
|
||||
@@ -372,18 +378,6 @@ func gasEstimateGasLimit(
|
||||
}
|
||||
ret = (ret * int64(transitionalMulti*1024)) >> 10
|
||||
|
||||
// Special case for PaymentChannel collect, which is deleting actor
|
||||
// We ignore errors in this special case since they CAN occur,
|
||||
// and we just want to detect existing payment channel actors
|
||||
st, err := smgr.ParentState(ts)
|
||||
if err == nil {
|
||||
act, err := st.GetActor(msg.To)
|
||||
if err == nil && lbuiltin.IsPaymentChannelActor(act.Code) && msgIn.Method == builtin.MethodsPaych.Collect {
|
||||
// add the refunded gas for DestroyActor back into the gas used
|
||||
ret += 76e3
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ const (
|
||||
|
||||
type LotusTraceEvent struct {
|
||||
Type pubsub_pb.TraceEvent_Type `json:"type,omitempty"`
|
||||
PeerID string `json:"peerID,omitempty"`
|
||||
PeerID []byte `json:"peerID,omitempty"`
|
||||
Timestamp *int64 `json:"timestamp,omitempty"`
|
||||
PeerScore TraceEventPeerScore `json:"peerScore,omitempty"`
|
||||
SourceAuth string `json:"sourceAuth,omitempty"`
|
||||
@@ -46,7 +46,7 @@ type TopicScore struct {
|
||||
}
|
||||
|
||||
type TraceEventPeerScore struct {
|
||||
PeerID string `json:"peerID"`
|
||||
PeerID []byte `json:"peerID"`
|
||||
Score float64 `json:"score"`
|
||||
AppSpecificScore float64 `json:"appSpecificScore"`
|
||||
IPColocationFactor float64 `json:"ipColocationFactor"`
|
||||
@@ -77,11 +77,11 @@ func (lt *lotusTracer) PeerScores(scores map[peer.ID]*pubsub.PeerScoreSnapshot)
|
||||
|
||||
evt := &LotusTraceEvent{
|
||||
Type: *TraceEventPeerScores.Enum(),
|
||||
PeerID: lt.pid.Pretty(),
|
||||
Timestamp: &now,
|
||||
PeerID: []byte(lt.pid),
|
||||
SourceAuth: lt.sa,
|
||||
PeerScore: TraceEventPeerScore{
|
||||
PeerID: pid.Pretty(),
|
||||
PeerID: []byte(pid),
|
||||
Score: score.Score,
|
||||
AppSpecificScore: score.AppSpecificScore,
|
||||
IPColocationFactor: score.IPColocationFactor,
|
||||
@@ -104,7 +104,6 @@ func (lt *lotusTracer) TraceLotusEvent(evt *LotusTraceEvent) {
|
||||
log.Errorf("error while transporting peer scores: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (lt *lotusTracer) Trace(evt *pubsub_pb.TraceEvent) {
|
||||
|
||||
@@ -30,16 +30,15 @@ func (ttt *testTracerTransport) Transport(evt TracerTransportEvent) error {
|
||||
}
|
||||
|
||||
func TestTracer_PeerScores(t *testing.T) {
|
||||
|
||||
testTransport := NewTestTraceTransport(t, func(t *testing.T, evt TracerTransportEvent) {
|
||||
require.Equal(t, peerIDA.Pretty(), evt.lotusTraceEvent.PeerID)
|
||||
require.Equal(t, []byte(peerIDA), evt.lotusTraceEvent.PeerID)
|
||||
require.Equal(t, "source-auth-token-test", evt.lotusTraceEvent.SourceAuth)
|
||||
require.Equal(t, float64(32), evt.lotusTraceEvent.PeerScore.Score)
|
||||
|
||||
n := time.Now().UnixNano()
|
||||
require.LessOrEqual(t, *evt.lotusTraceEvent.Timestamp, n)
|
||||
|
||||
require.Equal(t, peerIDA.Pretty(), evt.lotusTraceEvent.PeerScore.PeerID)
|
||||
require.Equal(t, []byte(peerIDA), evt.lotusTraceEvent.PeerScore.PeerID)
|
||||
require.Equal(t, 1, len(evt.lotusTraceEvent.PeerScore.Topics))
|
||||
|
||||
topic := evt.lotusTraceEvent.PeerScore.Topics[0]
|
||||
@@ -85,7 +84,6 @@ func TestTracer_PubSubTrace(t *testing.T) {
|
||||
PeerID: []byte(peerIDA),
|
||||
Timestamp: &n,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestTracer_MultipleTransports(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user