-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
Copy pathcommitment.go
169 lines (143 loc) · 5.27 KB
/
commitment.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package altda
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive/params"
"github.com/ethereum/go-ethereum/crypto"
)
// ErrInvalidCommitment is returned when the commitment cannot be parsed into a known commitment type.
var ErrInvalidCommitment = errors.New("invalid commitment")
// ErrCommitmentMismatch is returned when the commitment does not match the given input.
var ErrCommitmentMismatch = errors.New("commitment mismatch")
// CommitmentType is the commitment type prefix.
type CommitmentType byte
func CommitmentTypeFromString(s string) (CommitmentType, error) {
switch s {
case KeccakCommitmentString:
return Keccak256CommitmentType, nil
case GenericCommitmentString:
return GenericCommitmentType, nil
default:
return 0, fmt.Errorf("invalid commitment type: %s", s)
}
}
// CommitmentType describes the binary format of the commitment.
// KeccakCommitmentType is the default commitment type for the centralized DA storage.
// GenericCommitmentType indicates an opaque bytestring that the op-node never opens.
const (
Keccak256CommitmentType CommitmentType = 0
GenericCommitmentType CommitmentType = 1
KeccakCommitmentString string = "KeccakCommitment"
GenericCommitmentString string = "GenericCommitment"
)
// CommitmentData is the binary representation of a commitment.
type CommitmentData interface {
CommitmentType() CommitmentType
Encode() []byte
TxData() []byte
Verify(input []byte) error
String() string
}
// Keccak256Commitment is an implementation of CommitmentData that uses Keccak256 as the commitment function.
type Keccak256Commitment []byte
// GenericCommitment is an implementation of CommitmentData that treats the commitment as an opaque bytestring.
type GenericCommitment []byte
// NewCommitmentData creates a new commitment from the given input and desired type.
func NewCommitmentData(t CommitmentType, input []byte) CommitmentData {
switch t {
case Keccak256CommitmentType:
return NewKeccak256Commitment(input)
case GenericCommitmentType:
return NewGenericCommitment(input)
default:
return nil
}
}
// DecodeCommitmentData parses the commitment into a known commitment type.
// The input type is determined by the first byte of the raw data.
// The input type is discarded and the commitment is passed to the appropriate constructor.
func DecodeCommitmentData(input []byte) (CommitmentData, error) {
if len(input) == 0 {
return nil, ErrInvalidCommitment
}
t := CommitmentType(input[0])
data := input[1:]
switch t {
case Keccak256CommitmentType:
return DecodeKeccak256(data)
case GenericCommitmentType:
return DecodeGenericCommitment(data)
default:
return nil, ErrInvalidCommitment
}
}
// NewKeccak256Commitment creates a new commitment from the given input.
func NewKeccak256Commitment(input []byte) Keccak256Commitment {
return Keccak256Commitment(crypto.Keccak256(input))
}
// DecodeKeccak256 validates and casts the commitment into a Keccak256Commitment.
func DecodeKeccak256(commitment []byte) (Keccak256Commitment, error) {
// guard against empty commitments
if len(commitment) == 0 {
return nil, ErrInvalidCommitment
}
// keccak commitments are always 32 bytes
if len(commitment) != 32 {
return nil, ErrInvalidCommitment
}
return commitment, nil
}
// CommitmentType returns the commitment type of Keccak256.
func (c Keccak256Commitment) CommitmentType() CommitmentType {
return Keccak256CommitmentType
}
// Encode adds a commitment type prefix that describes the commitment.
func (c Keccak256Commitment) Encode() []byte {
return append([]byte{byte(Keccak256CommitmentType)}, c...)
}
// TxData adds an extra version byte to signal it's a commitment.
func (c Keccak256Commitment) TxData() []byte {
return append([]byte{params.DerivationVersion1}, c.Encode()...)
}
// Verify checks if the commitment matches the given input.
func (c Keccak256Commitment) Verify(input []byte) error {
if !bytes.Equal(c, crypto.Keccak256(input)) {
return ErrCommitmentMismatch
}
return nil
}
func (c Keccak256Commitment) String() string {
return hex.EncodeToString(c.Encode())
}
// NewGenericCommitment creates a new commitment from the given input.
func NewGenericCommitment(input []byte) GenericCommitment {
return GenericCommitment(input)
}
// DecodeGenericCommitment validates and casts the commitment into a GenericCommitment.
func DecodeGenericCommitment(commitment []byte) (GenericCommitment, error) {
if len(commitment) == 0 {
return nil, ErrInvalidCommitment
}
return commitment[:], nil
}
// CommitmentType returns the commitment type of Generic Commitment.
func (c GenericCommitment) CommitmentType() CommitmentType {
return GenericCommitmentType
}
// Encode adds a commitment type prefix self describing the commitment.
func (c GenericCommitment) Encode() []byte {
return append([]byte{byte(GenericCommitmentType)}, c...)
}
// TxData adds an extra version byte to signal it's a commitment.
func (c GenericCommitment) TxData() []byte {
return append([]byte{params.DerivationVersion1}, c.Encode()...)
}
// Verify always returns true for GenericCommitment because the DA Server must validate the data before returning it to the op-node.
func (c GenericCommitment) Verify(input []byte) error {
return nil
}
func (c GenericCommitment) String() string {
return hex.EncodeToString(c.Encode())
}