Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
49a4e9fa
Unverified
Commit
49a4e9fa
authored
Sep 06, 2024
by
protolambda
Committed by
GitHub
Sep 06, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-chain-ops: prep / utils for interop genesis work (#11790)
parent
afcc51a4
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
162 additions
and
16 deletions
+162
-16
devkeys.go
op-chain-ops/devkeys/devkeys.go
+14
-2
precompile.go
op-chain-ops/script/precompile.go
+56
-3
precompile_test.go
op-chain-ops/script/precompile_test.go
+22
-0
script.go
op-chain-ops/script/script.go
+66
-11
solutil.go
op-chain-ops/srcmap/solutil.go
+4
-0
No files found.
op-chain-ops/devkeys/devkeys.go
View file @
49a4e9fa
...
@@ -55,18 +55,26 @@ type SuperchainOperatorRole uint64
...
@@ -55,18 +55,26 @@ type SuperchainOperatorRole uint64
const
(
const
(
// SuperchainDeployerKey is the deployer of the superchain contracts.
// SuperchainDeployerKey is the deployer of the superchain contracts.
SuperchainDeployerKey
SuperchainOperatorRole
=
0
SuperchainDeployerKey
SuperchainOperatorRole
=
0
// SuperchainProxyAdminOwner is the key that owns the superchain ProxyAdmin
SuperchainProxyAdminOwner
SuperchainOperatorRole
=
1
// SuperchainConfigGuardianKey is the Guardian of the SuperchainConfig.
// SuperchainConfigGuardianKey is the Guardian of the SuperchainConfig.
SuperchainConfigGuardianKey
SuperchainOperatorRole
=
1
SuperchainConfigGuardianKey
SuperchainOperatorRole
=
2
// SuperchainProtocolVersionsOwner is the key that can make ProtocolVersions changes.
SuperchainProtocolVersionsOwner
SuperchainOperatorRole
=
3
// DependencySetManagerKey is the key used to manage the dependency set of a superchain.
// DependencySetManagerKey is the key used to manage the dependency set of a superchain.
DependencySetManagerKey
SuperchainOperatorRole
=
2
DependencySetManagerKey
SuperchainOperatorRole
=
4
)
)
func
(
role
SuperchainOperatorRole
)
String
()
string
{
func
(
role
SuperchainOperatorRole
)
String
()
string
{
switch
role
{
switch
role
{
case
SuperchainDeployerKey
:
case
SuperchainDeployerKey
:
return
"superchain-deployer"
return
"superchain-deployer"
case
SuperchainProxyAdminOwner
:
return
"superchain-proxy-admin-owner"
case
SuperchainConfigGuardianKey
:
case
SuperchainConfigGuardianKey
:
return
"superchain-config-guardian"
return
"superchain-config-guardian"
case
SuperchainProtocolVersionsOwner
:
return
"superchain-protocol-versions-owner"
case
DependencySetManagerKey
:
case
DependencySetManagerKey
:
return
"dependency-set-manager"
return
"dependency-set-manager"
default
:
default
:
...
@@ -122,6 +130,8 @@ const (
...
@@ -122,6 +130,8 @@ const (
L1FeeVaultRecipientRole
ChainOperatorRole
=
8
L1FeeVaultRecipientRole
ChainOperatorRole
=
8
// SequencerFeeVaultRecipientRole is the key that receives form the SequencerFeeVault predeploy
// SequencerFeeVaultRecipientRole is the key that receives form the SequencerFeeVault predeploy
SequencerFeeVaultRecipientRole
ChainOperatorRole
=
9
SequencerFeeVaultRecipientRole
ChainOperatorRole
=
9
// SystemConfigOwner is the key that can make SystemConfig changes.
SystemConfigOwner
ChainOperatorRole
=
10
)
)
func
(
role
ChainOperatorRole
)
String
()
string
{
func
(
role
ChainOperatorRole
)
String
()
string
{
...
@@ -146,6 +156,8 @@ func (role ChainOperatorRole) String() string {
...
@@ -146,6 +156,8 @@ func (role ChainOperatorRole) String() string {
return
"l1-fee-vault-recipient"
return
"l1-fee-vault-recipient"
case
SequencerFeeVaultRecipientRole
:
case
SequencerFeeVaultRecipientRole
:
return
"sequencer-fee-vault-recipient"
return
"sequencer-fee-vault-recipient"
case
SystemConfigOwner
:
return
"system-config-owner"
default
:
default
:
return
fmt
.
Sprintf
(
"unknown-operator-%d"
,
uint64
(
role
))
return
fmt
.
Sprintf
(
"unknown-operator-%d"
,
uint64
(
role
))
}
}
...
...
op-chain-ops/script/precompile.go
View file @
49a4e9fa
...
@@ -10,11 +10,15 @@ import (
...
@@ -10,11 +10,15 @@ import (
"strings"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
)
)
var
setterFnSig
=
"set(bytes4,address)"
var
setterFnBytes4
=
bytes4
(
setterFnSig
)
// precompileFunc is a prepared function to perform a method call / field read with ABI decoding/encoding.
// precompileFunc is a prepared function to perform a method call / field read with ABI decoding/encoding.
type
precompileFunc
struct
{
type
precompileFunc
struct
{
goName
string
goName
string
...
@@ -52,12 +56,20 @@ func rightPad32(data []byte) []byte {
...
@@ -52,12 +56,20 @@ func rightPad32(data []byte) []byte {
return
append
(
out
,
make
([]
byte
,
32
-
(
len
(
out
)
%
32
))
...
)
return
append
(
out
,
make
([]
byte
,
32
-
(
len
(
out
)
%
32
))
...
)
}
}
type
settableField
struct
{
name
string
value
*
reflect
.
Value
}
// Precompile is a wrapper around a Go object, making it a precompile.
// Precompile is a wrapper around a Go object, making it a precompile.
type
Precompile
[
E
any
]
struct
{
type
Precompile
[
E
any
]
struct
{
Precompile
E
Precompile
E
fieldsOnly
bool
fieldsOnly
bool
fieldSetter
bool
settable
map
[[
4
]
byte
]
*
settableField
// abiMethods is effectively the jump-table for 4-byte ABI calls to the precompile.
// abiMethods is effectively the jump-table for 4-byte ABI calls to the precompile.
abiMethods
map
[[
4
]
byte
]
*
precompileFunc
abiMethods
map
[[
4
]
byte
]
*
precompileFunc
}
}
...
@@ -70,6 +82,10 @@ func WithFieldsOnly[E any](p *Precompile[E]) {
...
@@ -70,6 +82,10 @@ func WithFieldsOnly[E any](p *Precompile[E]) {
p
.
fieldsOnly
=
true
p
.
fieldsOnly
=
true
}
}
func
WithFieldSetter
[
E
any
](
p
*
Precompile
[
E
])
{
p
.
fieldSetter
=
true
}
// NewPrecompile wraps a Go object into a Precompile.
// NewPrecompile wraps a Go object into a Precompile.
// All exported fields and methods will have a corresponding ABI interface.
// All exported fields and methods will have a corresponding ABI interface.
// Fields with a tag `evm:"-"` will be ignored, or can override their ABI name to x with this tag: `evm:"x"`.
// Fields with a tag `evm:"-"` will be ignored, or can override their ABI name to x with this tag: `evm:"x"`.
...
@@ -83,6 +99,8 @@ func NewPrecompile[E any](e E, opts ...PrecompileOption[E]) (*Precompile[E], err
...
@@ -83,6 +99,8 @@ func NewPrecompile[E any](e E, opts ...PrecompileOption[E]) (*Precompile[E], err
Precompile
:
e
,
Precompile
:
e
,
abiMethods
:
make
(
map
[[
4
]
byte
]
*
precompileFunc
),
abiMethods
:
make
(
map
[[
4
]
byte
]
*
precompileFunc
),
fieldsOnly
:
false
,
fieldsOnly
:
false
,
fieldSetter
:
false
,
settable
:
make
(
map
[[
4
]
byte
]
*
settableField
),
}
}
for
_
,
opt
:=
range
opts
{
for
_
,
opt
:=
range
opts
{
opt
(
out
)
opt
(
out
)
...
@@ -96,6 +114,8 @@ func NewPrecompile[E any](e E, opts ...PrecompileOption[E]) (*Precompile[E], err
...
@@ -96,6 +114,8 @@ func NewPrecompile[E any](e E, opts ...PrecompileOption[E]) (*Precompile[E], err
if
err
:=
out
.
setupFields
(
&
elemVal
);
err
!=
nil
{
if
err
:=
out
.
setupFields
(
&
elemVal
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to setup fields of precompile: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to setup fields of precompile: %w"
,
err
)
}
}
// create setter that can handle of the fields
out
.
setupFieldSetter
()
return
out
,
nil
return
out
,
nil
}
}
...
@@ -496,9 +516,42 @@ func (p *Precompile[E]) setupStructField(fieldDef *reflect.StructField, fieldVal
...
@@ -496,9 +516,42 @@ func (p *Precompile[E]) setupStructField(fieldDef *reflect.StructField, fieldVal
abiSignature
:
methodSig
,
abiSignature
:
methodSig
,
fn
:
fn
,
fn
:
fn
,
}
}
// register field as settable
if
p
.
fieldSetter
&&
fieldDef
.
Type
.
AssignableTo
(
typeFor
[
common
.
Address
]())
{
p
.
settable
[
byte4Sig
]
=
&
settableField
{
name
:
fieldDef
.
Name
,
value
:
fieldVal
,
}
}
return
nil
return
nil
}
}
func
(
p
*
Precompile
[
E
])
setupFieldSetter
()
{
if
!
p
.
fieldSetter
{
return
}
p
.
abiMethods
[
setterFnBytes4
]
=
&
precompileFunc
{
goName
:
"__fieldSetter___"
,
abiSignature
:
setterFnSig
,
fn
:
func
(
input
[]
byte
)
([]
byte
,
error
)
{
if
len
(
input
)
!=
32
*
2
{
return
nil
,
fmt
.
Errorf
(
"cannot set address field to %d bytes"
,
len
(
input
))
}
if
[
32
-
4
]
byte
(
input
[
4
:
32
])
!=
([
32
-
4
]
byte
{})
{
return
nil
,
fmt
.
Errorf
(
"unexpected selector content, input: %x"
,
input
[
:
])
}
selector
:=
[
4
]
byte
(
input
[
:
4
])
f
,
ok
:=
p
.
settable
[
selector
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"unknown address field selector 0x%x"
,
selector
)
}
addr
:=
common
.
Address
(
input
[
32
*
2
-
20
:
32
*
2
])
f
.
value
.
Set
(
reflect
.
ValueOf
(
addr
))
return
nil
,
nil
},
}
}
// RequiredGas is part of the vm.PrecompiledContract interface, and all system precompiles use 0 gas.
// RequiredGas is part of the vm.PrecompiledContract interface, and all system precompiles use 0 gas.
func
(
p
*
Precompile
[
E
])
RequiredGas
(
input
[]
byte
)
uint64
{
func
(
p
*
Precompile
[
E
])
RequiredGas
(
input
[]
byte
)
uint64
{
return
0
return
0
...
...
op-chain-ops/script/precompile_test.go
View file @
49a4e9fa
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
)
)
...
@@ -119,3 +120,24 @@ func TestPrecompile(t *testing.T) {
...
@@ -119,3 +120,24 @@ func TestPrecompile(t *testing.T) {
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
b32
((
42
+
100
+
7
)
*
3
),
out
)
require
.
Equal
(
t
,
b32
((
42
+
100
+
7
)
*
3
),
out
)
}
}
type
DeploymentExample
struct
{
FooBar
common
.
Address
}
func
TestDeploymentOutputPrecompile
(
t
*
testing
.
T
)
{
e
:=
&
DeploymentExample
{}
p
,
err
:=
NewPrecompile
[
*
DeploymentExample
](
e
,
WithFieldSetter
[
*
DeploymentExample
])
require
.
NoError
(
t
,
err
)
addr
:=
common
.
Address
{
0
:
0x42
,
19
:
0xaa
}
fooBarSelector
:=
bytes4
(
"fooBar()"
)
var
input
[]
byte
input
=
append
(
input
,
setterFnBytes4
[
:
]
...
)
input
=
append
(
input
,
rightPad32
(
fooBarSelector
[
:
])
...
)
input
=
append
(
input
,
leftPad32
(
addr
[
:
])
...
)
out
,
err
:=
p
.
Run
(
input
)
require
.
NoError
(
t
,
err
)
require
.
Empty
(
t
,
out
)
require
.
Equal
(
t
,
addr
,
e
.
FooBar
)
}
op-chain-ops/script/script.go
View file @
49a4e9fa
...
@@ -29,6 +29,9 @@ import (
...
@@ -29,6 +29,9 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/srcmap"
"github.com/ethereum-optimism/optimism/op-chain-ops/srcmap"
)
)
// jumpHistory is the amount of successful jumps to track for debugging.
const
jumpHistory
=
5
// CallFrame encodes the scope context of the current call
// CallFrame encodes the scope context of the current call
type
CallFrame
struct
{
type
CallFrame
struct
{
Depth
int
Depth
int
...
@@ -39,7 +42,9 @@ type CallFrame struct {
...
@@ -39,7 +42,9 @@ type CallFrame struct {
// Reverts often happen in generated code.
// Reverts often happen in generated code.
// We want to fallback to logging the source-map position of
// We want to fallback to logging the source-map position of
// the non-generated code, i.e. the origin of the last successful jump.
// the non-generated code, i.e. the origin of the last successful jump.
LastJumpPC
uint64
// And beyond that, a short history of the latest jumps is useful for debugging.
// This is a list of program-counters at the time of the jump (i.e. before raching JUMPDEST).
LastJumps
[]
uint64
Ctx
*
vm
.
ScopeContext
Ctx
*
vm
.
ScopeContext
...
@@ -79,6 +84,8 @@ type Host struct {
...
@@ -79,6 +84,8 @@ type Host struct {
// src-maps are disabled if this is nil.
// src-maps are disabled if this is nil.
srcFS
*
foundry
.
SourceMapFS
srcFS
*
foundry
.
SourceMapFS
srcMaps
map
[
common
.
Address
]
*
srcmap
.
SourceMap
srcMaps
map
[
common
.
Address
]
*
srcmap
.
SourceMap
onLabel
[]
func
(
name
string
,
addr
common
.
Address
)
}
}
// NewHost creates a Host that can load contracts from the given Artifacts FS,
// NewHost creates a Host that can load contracts from the given Artifacts FS,
...
@@ -381,7 +388,6 @@ func (h *Host) onOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpCo
...
@@ -381,7 +388,6 @@ func (h *Host) onOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpCo
Depth
:
depth
,
Depth
:
depth
,
LastOp
:
vm
.
OpCode
(
op
),
LastOp
:
vm
.
OpCode
(
op
),
LastPC
:
pc
,
LastPC
:
pc
,
LastJumpPC
:
pc
,
Ctx
:
scopeCtx
,
Ctx
:
scopeCtx
,
})
})
}
}
...
@@ -391,7 +397,11 @@ func (h *Host) onOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpCo
...
@@ -391,7 +397,11 @@ func (h *Host) onOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpCo
}
}
cf
:=
&
h
.
callStack
[
len
(
h
.
callStack
)
-
1
]
cf
:=
&
h
.
callStack
[
len
(
h
.
callStack
)
-
1
]
if
vm
.
OpCode
(
op
)
==
vm
.
JUMPDEST
{
// remember the last PC before successful jump
if
vm
.
OpCode
(
op
)
==
vm
.
JUMPDEST
{
// remember the last PC before successful jump
cf
.
LastJumpPC
=
cf
.
LastPC
cf
.
LastJumps
=
append
(
cf
.
LastJumps
,
cf
.
LastPC
)
if
len
(
cf
.
LastJumps
)
>
jumpHistory
{
copy
(
cf
.
LastJumps
[
:
],
cf
.
LastJumps
[
len
(
cf
.
LastJumps
)
-
jumpHistory
:
])
cf
.
LastJumps
=
cf
.
LastJumps
[
:
jumpHistory
]
}
}
}
cf
.
LastOp
=
vm
.
OpCode
(
op
)
cf
.
LastOp
=
vm
.
OpCode
(
op
)
cf
.
LastPC
=
pc
cf
.
LastPC
=
pc
...
@@ -527,10 +537,14 @@ func (h *Host) EnforceMaxCodeSize(v bool) {
...
@@ -527,10 +537,14 @@ func (h *Host) EnforceMaxCodeSize(v bool) {
func
(
h
*
Host
)
LogCallStack
()
{
func
(
h
*
Host
)
LogCallStack
()
{
for
_
,
cf
:=
range
h
.
callStack
{
for
_
,
cf
:=
range
h
.
callStack
{
callsite
:=
""
callsite
:=
""
if
srcMap
,
ok
:=
h
.
srcMaps
[
cf
.
Ctx
.
Address
()];
ok
{
srcMap
,
ok
:=
h
.
srcMaps
[
cf
.
Ctx
.
Address
()]
if
!
ok
&&
cf
.
Ctx
.
Contract
.
CodeAddr
!=
nil
{
// if delegate-call, we might know the implementation code.
srcMap
,
ok
=
h
.
srcMaps
[
*
cf
.
Ctx
.
Contract
.
CodeAddr
]
}
if
ok
{
callsite
=
srcMap
.
FormattedInfo
(
cf
.
LastPC
)
callsite
=
srcMap
.
FormattedInfo
(
cf
.
LastPC
)
if
callsite
==
"unknown:0:0"
{
if
callsite
==
"unknown:0:0"
&&
len
(
cf
.
LastJumps
)
>
0
{
callsite
=
srcMap
.
FormattedInfo
(
cf
.
LastJump
PC
)
callsite
=
srcMap
.
FormattedInfo
(
cf
.
LastJump
s
[
len
(
cf
.
LastJumps
)
-
1
]
)
}
}
}
}
input
:=
cf
.
Ctx
.
CallInput
()
input
:=
cf
.
Ctx
.
CallInput
()
...
@@ -538,9 +552,14 @@ func (h *Host) LogCallStack() {
...
@@ -538,9 +552,14 @@ func (h *Host) LogCallStack() {
if
len
(
input
)
>=
4
{
if
len
(
input
)
>=
4
{
byte4
=
fmt
.
Sprintf
(
"0x%x"
,
input
[
:
4
])
byte4
=
fmt
.
Sprintf
(
"0x%x"
,
input
[
:
4
])
}
}
h
.
log
.
Debug
(
"callframe"
,
"depth"
,
cf
.
Depth
,
"input"
,
hexutil
.
Bytes
(
input
),
"pc"
,
cf
.
LastPC
,
"op"
,
cf
.
LastOp
)
h
.
log
.
Debug
(
"callframe
input
"
,
"depth"
,
cf
.
Depth
,
"input"
,
hexutil
.
Bytes
(
input
),
"pc"
,
cf
.
LastPC
,
"op"
,
cf
.
LastOp
)
h
.
log
.
Warn
(
"callframe"
,
"depth"
,
cf
.
Depth
,
"byte4"
,
byte4
,
h
.
log
.
Warn
(
"callframe"
,
"depth"
,
cf
.
Depth
,
"byte4"
,
byte4
,
"addr"
,
cf
.
Ctx
.
Address
(),
"callsite"
,
callsite
,
"label"
,
h
.
labels
[
cf
.
Ctx
.
Address
()])
"addr"
,
cf
.
Ctx
.
Address
(),
"callsite"
,
callsite
,
"label"
,
h
.
labels
[
cf
.
Ctx
.
Address
()])
if
srcMap
!=
nil
{
for
_
,
jmpPC
:=
range
cf
.
LastJumps
{
h
.
log
.
Debug
(
"recent jump"
,
"depth"
,
cf
.
Depth
,
"callsite"
,
srcMap
.
FormattedInfo
(
jmpPC
),
"pc"
,
jmpPC
)
}
}
}
}
}
}
...
@@ -548,4 +567,40 @@ func (h *Host) LogCallStack() {
...
@@ -548,4 +567,40 @@ func (h *Host) LogCallStack() {
func
(
h
*
Host
)
Label
(
addr
common
.
Address
,
label
string
)
{
func
(
h
*
Host
)
Label
(
addr
common
.
Address
,
label
string
)
{
h
.
log
.
Debug
(
"labeling"
,
"addr"
,
addr
,
"label"
,
label
)
h
.
log
.
Debug
(
"labeling"
,
"addr"
,
addr
,
"label"
,
label
)
h
.
labels
[
addr
]
=
label
h
.
labels
[
addr
]
=
label
for
_
,
fn
:=
range
h
.
onLabel
{
fn
(
label
,
addr
)
}
}
// NewScriptAddress creates a new address for the ScriptDeployer account, and bumps the nonce.
func
(
h
*
Host
)
NewScriptAddress
()
common
.
Address
{
deployer
:=
ScriptDeployer
deployNonce
:=
h
.
state
.
GetNonce
(
deployer
)
// compute address of script contract to be deployed
addr
:=
crypto
.
CreateAddress
(
deployer
,
deployNonce
)
h
.
state
.
SetNonce
(
deployer
,
deployNonce
+
1
)
return
addr
}
func
(
h
*
Host
)
ChainID
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
h
.
chainCfg
.
ChainID
)
}
func
(
h
*
Host
)
Artifacts
()
*
foundry
.
ArtifactsFS
{
return
h
.
af
}
// RememberOnLabel links the contract source-code of srcFile upon a given label
func
(
h
*
Host
)
RememberOnLabel
(
label
,
srcFile
,
contract
string
)
error
{
artifact
,
err
:=
h
.
af
.
ReadArtifact
(
srcFile
,
contract
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to read artifact %s (contract %s) for label %q"
,
srcFile
,
contract
,
label
)
}
h
.
onLabel
=
append
(
h
.
onLabel
,
func
(
v
string
,
addr
common
.
Address
)
{
if
label
==
v
{
h
.
RememberArtifact
(
addr
,
artifact
,
contract
)
}
})
return
nil
}
}
op-chain-ops/srcmap/solutil.go
View file @
49a4e9fa
...
@@ -120,6 +120,10 @@ type SourceMap struct {
...
@@ -120,6 +120,10 @@ type SourceMap struct {
// This location is the source file-path, the line number, and column number.
// This location is the source file-path, the line number, and column number.
// This may return an error, as the source-file is lazy-loaded to calculate the position data.
// This may return an error, as the source-file is lazy-loaded to calculate the position data.
func
(
s
*
SourceMap
)
Info
(
pc
uint64
)
(
source
string
,
line
uint32
,
col
uint32
,
err
error
)
{
func
(
s
*
SourceMap
)
Info
(
pc
uint64
)
(
source
string
,
line
uint32
,
col
uint32
,
err
error
)
{
if
pc
>=
uint64
(
len
(
s
.
Instr
))
{
source
=
"invalid"
return
}
instr
:=
s
.
Instr
[
pc
]
instr
:=
s
.
Instr
[
pc
]
if
instr
.
F
<
0
||
instr
==
(
InstrMapping
{})
{
if
instr
.
F
<
0
||
instr
==
(
InstrMapping
{})
{
return
"generated"
,
0
,
0
,
nil
return
"generated"
,
0
,
0
,
nil
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment