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
0649c9d0
Unverified
Commit
0649c9d0
authored
Sep 14, 2022
by
Mark Tyneway
Committed by
GitHub
Sep 14, 2022
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3462 from ethereum-optimism/feat/xdm
op-chain-ops: cross domain message
parents
df041c0e
bb2ae1d9
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
316 additions
and
0 deletions
+316
-0
encoding.go
op-chain-ops/crossdomain/encoding.go
+72
-0
encoding_test.go
op-chain-ops/crossdomain/encoding_test.go
+30
-0
hashing.go
op-chain-ops/crossdomain/hashing.go
+42
-0
message.go
op-chain-ops/crossdomain/message.go
+72
-0
message_test.go
op-chain-ops/crossdomain/message_test.go
+100
-0
No files found.
op-chain-ops/crossdomain/encoding.go
0 → 100644
View file @
0649c9d0
package
crossdomain
import
(
"math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)
var
(
// NonceMask represents a mask used to extract version bytes from the nonce
NonceMask
,
_
=
new
(
big
.
Int
)
.
SetString
(
"0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
16
)
// relayMessage0ABI represents the v0 relay message encoding
relayMessage0ABI
=
"[{
\"
inputs
\"
:[{
\"
internalType
\"
:
\"
address
\"
,
\"
name
\"
:
\"
_target
\"
,
\"
type
\"
:
\"
address
\"
},{
\"
internalType
\"
:
\"
address
\"
,
\"
name
\"
:
\"
_sender
\"
,
\"
type
\"
:
\"
address
\"
},{
\"
internalType
\"
:
\"
bytes
\"
,
\"
name
\"
:
\"
_message
\"
,
\"
type
\"
:
\"
bytes
\"
},{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
_messageNonce
\"
,
\"
type
\"
:
\"
uint256
\"
}],
\"
name
\"
:
\"
relayMessage
\"
,
\"
outputs
\"
:[],
\"
stateMutability
\"
:
\"
nonpayable
\"
,
\"
type
\"
:
\"
function
\"
}]"
// relayMessage1ABI represents the v1 relay message encoding
relayMessage1ABI
=
"[{
\"
inputs
\"
:[{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
_nonce
\"
,
\"
type
\"
:
\"
uint256
\"
},{
\"
internalType
\"
:
\"
address
\"
,
\"
name
\"
:
\"
_sender
\"
,
\"
type
\"
:
\"
address
\"
},{
\"
internalType
\"
:
\"
address
\"
,
\"
name
\"
:
\"
_target
\"
,
\"
type
\"
:
\"
address
\"
},{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
_value
\"
,
\"
type
\"
:
\"
uint256
\"
},{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
_minGasLimit
\"
,
\"
type
\"
:
\"
uint256
\"
},{
\"
internalType
\"
:
\"
bytes
\"
,
\"
name
\"
:
\"
_message
\"
,
\"
type
\"
:
\"
bytes
\"
}],
\"
name
\"
:
\"
relayMessage
\"
,
\"
outputs
\"
:[],
\"
stateMutability
\"
:
\"
payable
\"
,
\"
type
\"
:
\"
function
\"
}]"
// relayMessage0 represents the ABI of relay message v0
relayMessage0
abi
.
ABI
// relayMessage1 represents the ABI of relay message v1
relayMessage1
abi
.
ABI
)
// Create the required ABIs
func
init
()
{
var
err
error
relayMessage0
,
err
=
abi
.
JSON
(
strings
.
NewReader
(
relayMessage0ABI
))
if
err
!=
nil
{
panic
(
err
)
}
relayMessage1
,
err
=
abi
.
JSON
(
strings
.
NewReader
(
relayMessage1ABI
))
if
err
!=
nil
{
panic
(
err
)
}
}
// EncodeCrossDomainMessageV0 will encode the calldata for
// "relayMessage(address,address,bytes,uint256)",
func
EncodeCrossDomainMessageV0
(
target
*
common
.
Address
,
sender
*
common
.
Address
,
message
[]
byte
,
nonce
*
big
.
Int
,
)
([]
byte
,
error
)
{
return
relayMessage0
.
Pack
(
"relayMessage"
,
target
,
sender
,
message
,
nonce
)
}
// EncodeCrossDomainMessageV1 will encode the calldata for
// "relayMessage(uint256,address,address,uint256,uint256,bytes)",
func
EncodeCrossDomainMessageV1
(
nonce
*
big
.
Int
,
sender
*
common
.
Address
,
target
*
common
.
Address
,
value
*
big
.
Int
,
gasLimit
*
big
.
Int
,
data
[]
byte
,
)
([]
byte
,
error
)
{
return
relayMessage1
.
Pack
(
"relayMessage"
,
nonce
,
sender
,
target
,
value
,
gasLimit
,
data
)
}
// DecodeVersionedNonce will decode the version that is encoded in the nonce
func
DecodeVersionedNonce
(
versioned
*
big
.
Int
)
(
*
big
.
Int
,
*
big
.
Int
)
{
nonce
:=
new
(
big
.
Int
)
.
And
(
versioned
,
NonceMask
)
version
:=
new
(
big
.
Int
)
.
Rsh
(
versioned
,
240
)
return
nonce
,
version
}
// EncodeVersionedNonce will encode the version into the nonce
func
EncodeVersionedNonce
(
nonce
,
version
*
big
.
Int
)
*
big
.
Int
{
shifted
:=
new
(
big
.
Int
)
.
Lsh
(
version
,
240
)
return
new
(
big
.
Int
)
.
Or
(
nonce
,
shifted
)
}
op-chain-ops/crossdomain/encoding_test.go
0 → 100644
View file @
0649c9d0
package
crossdomain_test
import
(
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/stretchr/testify/require"
)
func
FuzzVersionedNonce
(
f
*
testing
.
F
)
{
f
.
Fuzz
(
func
(
t
*
testing
.
T
,
_nonce
[]
byte
,
_version
uint16
)
{
inputNonce
:=
new
(
big
.
Int
)
.
SetBytes
(
_nonce
)
// Clamp nonce to uint240
if
inputNonce
.
Cmp
(
crossdomain
.
NonceMask
)
>
0
{
inputNonce
=
new
(
big
.
Int
)
.
Set
(
crossdomain
.
NonceMask
)
}
// Clamp version to 0 or 1
_version
=
_version
%
2
inputVersion
:=
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
_version
))
encodedNonce
:=
crossdomain
.
EncodeVersionedNonce
(
inputNonce
,
inputVersion
)
decodedNonce
,
decodedVersion
:=
crossdomain
.
DecodeVersionedNonce
(
encodedNonce
)
require
.
Equal
(
t
,
decodedNonce
.
Uint64
(),
inputNonce
.
Uint64
())
require
.
Equal
(
t
,
decodedVersion
.
Uint64
(),
inputVersion
.
Uint64
())
})
}
op-chain-ops/crossdomain/hashing.go
0 → 100644
View file @
0649c9d0
package
crossdomain
import
(
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
// HashCrossDomainMessageV0 computes the pre bedrock cross domain messaging
// hashing scheme.
func
HashCrossDomainMessageV0
(
target
*
common
.
Address
,
sender
*
common
.
Address
,
data
[]
byte
,
nonce
*
big
.
Int
,
)
(
common
.
Hash
,
error
)
{
encoded
,
err
:=
EncodeCrossDomainMessageV0
(
target
,
sender
,
data
,
nonce
)
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
hash
:=
crypto
.
Keccak256
(
encoded
)
return
common
.
BytesToHash
(
hash
),
nil
}
// HashCrossDomainMessageV1 computes the first post bedrock cross domain
// messaging hashing scheme.
func
HashCrossDomainMessageV1
(
nonce
*
big
.
Int
,
sender
*
common
.
Address
,
target
*
common
.
Address
,
value
*
big
.
Int
,
gasLimit
*
big
.
Int
,
data
[]
byte
,
)
(
common
.
Hash
,
error
)
{
encoded
,
err
:=
EncodeCrossDomainMessageV1
(
nonce
,
sender
,
target
,
value
,
gasLimit
,
data
)
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
hash
:=
crypto
.
Keccak256
(
encoded
)
return
common
.
BytesToHash
(
hash
),
nil
}
op-chain-ops/crossdomain/message.go
0 → 100644
View file @
0649c9d0
package
crossdomain
import
(
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
// CrossDomainMessage represents a cross domain message
// used by the CrossDomainMessenger. The version is encoded
// in the nonce. Version 0 messages do not have a value,
// version 1 messages have a value and the most significant
// byte of the nonce is a 1
type
CrossDomainMessage
struct
{
Nonce
*
big
.
Int
Sender
*
common
.
Address
Target
*
common
.
Address
Value
*
big
.
Int
GasLimit
*
big
.
Int
Data
[]
byte
}
// NewCrossDomainMessage creates a CrossDomainMessage.
func
NewCrossDomainMessage
(
nonce
*
big
.
Int
,
sender
,
target
*
common
.
Address
,
value
,
gasLimit
*
big
.
Int
,
data
[]
byte
,
)
*
CrossDomainMessage
{
return
&
CrossDomainMessage
{
Nonce
:
nonce
,
Sender
:
sender
,
Target
:
target
,
Value
:
value
,
GasLimit
:
gasLimit
,
Data
:
data
,
}
}
// Version will return the version of the CrossDomainMessage.
// It does this by looking at the first byte of the nonce.
func
(
c
*
CrossDomainMessage
)
Version
()
uint64
{
_
,
version
:=
DecodeVersionedNonce
(
c
.
Nonce
)
return
version
.
Uint64
()
}
// Encode will encode a cross domain message based on the version.
func
(
c
*
CrossDomainMessage
)
Encode
()
([]
byte
,
error
)
{
version
:=
c
.
Version
()
switch
version
{
case
0
:
return
EncodeCrossDomainMessageV0
(
c
.
Target
,
c
.
Sender
,
c
.
Data
,
c
.
Nonce
)
case
1
:
return
EncodeCrossDomainMessageV1
(
c
.
Nonce
,
c
.
Sender
,
c
.
Target
,
c
.
Value
,
c
.
GasLimit
,
c
.
Data
)
default
:
return
nil
,
fmt
.
Errorf
(
"unknown nonce version %d"
,
version
)
}
}
// Hash will compute the hash of the CrossDomainMessage
func
(
c
*
CrossDomainMessage
)
Hash
()
(
common
.
Hash
,
error
)
{
version
:=
c
.
Version
()
switch
version
{
case
0
:
return
HashCrossDomainMessageV0
(
c
.
Target
,
c
.
Sender
,
c
.
Data
,
c
.
Nonce
)
case
1
:
return
HashCrossDomainMessageV1
(
c
.
Nonce
,
c
.
Sender
,
c
.
Target
,
c
.
Value
,
c
.
GasLimit
,
c
.
Data
)
default
:
return
common
.
Hash
{},
fmt
.
Errorf
(
"unknown nonce version %d"
,
version
)
}
}
op-chain-ops/crossdomain/message_test.go
0 → 100644
View file @
0649c9d0
package
crossdomain_test
import
(
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"
)
// TestEncode tests the encoding of a CrossDomainMessage. The assertion was
// created using solidity.
func
TestEncode
(
t
*
testing
.
T
)
{
t
.
Parallel
()
t
.
Run
(
"V0"
,
func
(
t
*
testing
.
T
)
{
msg
:=
crossdomain
.
NewCrossDomainMessage
(
crossdomain
.
EncodeVersionedNonce
(
common
.
Big0
,
common
.
Big0
),
&
common
.
Address
{},
&
common
.
Address
{
19
:
0x01
},
big
.
NewInt
(
0
),
big
.
NewInt
(
5
),
[]
byte
{},
)
require
.
Equal
(
t
,
uint64
(
0
),
msg
.
Version
())
encoded
,
err
:=
msg
.
Encode
()
require
.
Nil
(
t
,
err
)
expect
:=
hexutil
.
MustDecode
(
"0xcbd4ece900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
)
require
.
Equal
(
t
,
expect
,
encoded
)
})
t
.
Run
(
"V1"
,
func
(
t
*
testing
.
T
)
{
msg
:=
crossdomain
.
NewCrossDomainMessage
(
crossdomain
.
EncodeVersionedNonce
(
common
.
Big1
,
common
.
Big1
),
&
common
.
Address
{
19
:
0x01
},
&
common
.
Address
{
19
:
0x02
},
big
.
NewInt
(
100
),
big
.
NewInt
(
555
),
[]
byte
{},
)
require
.
Equal
(
t
,
uint64
(
1
),
msg
.
Version
())
encoded
,
err
:=
msg
.
Encode
()
require
.
Nil
(
t
,
err
)
expect
:=
hexutil
.
MustDecode
(
"0xd764ad0b0001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000022b00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000"
)
require
.
Equal
(
t
,
expect
,
encoded
)
})
}
// TestEncode tests the hash of a CrossDomainMessage. The assertion was
// created using solidity.
func
TestHash
(
t
*
testing
.
T
)
{
t
.
Parallel
()
t
.
Run
(
"V0"
,
func
(
t
*
testing
.
T
)
{
msg
:=
crossdomain
.
NewCrossDomainMessage
(
crossdomain
.
EncodeVersionedNonce
(
common
.
Big0
,
common
.
Big0
),
&
common
.
Address
{},
&
common
.
Address
{
19
:
0x01
},
big
.
NewInt
(
10
),
big
.
NewInt
(
5
),
[]
byte
{},
)
require
.
Equal
(
t
,
uint64
(
0
),
msg
.
Version
())
hash
,
err
:=
msg
.
Hash
()
require
.
Nil
(
t
,
err
)
expect
:=
common
.
HexToHash
(
"0x5bb579a193681e7c4d43c8c2e4bc6c2c447d21ef9fa887ca23b2d3f9a0fac065"
)
require
.
Equal
(
t
,
expect
,
hash
)
})
t
.
Run
(
"V1"
,
func
(
t
*
testing
.
T
)
{
msg
:=
crossdomain
.
NewCrossDomainMessage
(
crossdomain
.
EncodeVersionedNonce
(
common
.
Big0
,
common
.
Big1
),
&
common
.
Address
{},
&
common
.
Address
{
19
:
0x01
},
big
.
NewInt
(
0
),
big
.
NewInt
(
5
),
[]
byte
{},
)
require
.
Equal
(
t
,
uint64
(
1
),
msg
.
Version
())
hash
,
err
:=
msg
.
Hash
()
require
.
Nil
(
t
,
err
)
expect
:=
common
.
HexToHash
(
"0x09bbda7f59cdaccab5c41cab4600bd458b2bd7d9f8410f13316fe07e5f4237cc"
)
require
.
Equal
(
t
,
expect
,
hash
)
})
}
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