-
Notifications
You must be signed in to change notification settings - Fork 38
/
enclave_init_service.go
155 lines (138 loc) · 6.03 KB
/
enclave_init_service.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
package enclave
import (
"context"
"errors"
"fmt"
"math/big"
"github.com/ten-protocol/go-ten/go/enclave/components"
enclaveconfig "github.com/ten-protocol/go-ten/go/enclave/config"
"github.com/ten-protocol/go-ten/go/enclave/storage"
"github.com/ten-protocol/go-ten/go/responses"
"github.com/ten-protocol/go-ten/go/common"
"github.com/ten-protocol/go-ten/go/common/log"
_ "github.com/ten-protocol/go-ten/go/common/tracers/native" // make sure the tracers are loaded
"github.com/ten-protocol/go-ten/go/enclave/crypto"
gethcommon "github.com/ethereum/go-ethereum/common"
gethlog "github.com/ethereum/go-ethereum/log"
)
var _noHeadBatch = big.NewInt(0)
type enclaveInitService struct {
config *enclaveconfig.EnclaveConfig
storage storage.Storage
l1BlockProcessor components.L1BlockProcessor
logger gethlog.Logger
sharedSecretService *crypto.SharedSecretService
enclaveKeyService *crypto.EnclaveAttestedKeyService // the enclave's private key (used to identify the enclave and sign messages)
attestationProvider components.AttestationProvider // interface for producing attestation reports and verifying them
daEncryptionService *crypto.DAEncryptionService
rpcKeyService *crypto.RPCKeyService
}
func NewEnclaveInitAPI(config *enclaveconfig.EnclaveConfig, storage storage.Storage, logger gethlog.Logger, l1BlockProcessor components.L1BlockProcessor, enclaveKeyService *crypto.EnclaveAttestedKeyService, attestationProvider components.AttestationProvider, sharedSecretService *crypto.SharedSecretService, daEncryptionService *crypto.DAEncryptionService, rpcKeyService *crypto.RPCKeyService) common.EnclaveInit {
return &enclaveInitService{
config: config,
storage: storage,
l1BlockProcessor: l1BlockProcessor,
logger: logger,
enclaveKeyService: enclaveKeyService,
attestationProvider: attestationProvider,
sharedSecretService: sharedSecretService,
daEncryptionService: daEncryptionService,
rpcKeyService: rpcKeyService,
}
}
// Status is only implemented by the RPC wrapper
func (e *enclaveInitService) Status(ctx context.Context) (common.Status, common.SystemError) {
initialised := e.sharedSecretService.IsInitialised()
if !initialised {
return common.Status{StatusCode: common.AwaitingSecret, L2Head: _noHeadBatch}, nil
}
var l1HeadHash gethcommon.Hash
l1Head, err := e.l1BlockProcessor.GetHead(ctx)
if err != nil {
// this might be normal while enclave is starting up, just send empty hash
e.logger.Debug("failed to fetch L1 head block for status response", log.ErrKey, err)
} else {
l1HeadHash = l1Head.Hash()
}
// we use zero when there's no head batch yet, the first seq number is 1
l2HeadSeqNo := _noHeadBatch
// this is the highest seq number that has been received and stored on the enclave (it may not have been executed)
currSeqNo, err := e.storage.FetchCurrentSequencerNo(ctx)
if err != nil {
// this might be normal while enclave is starting up, just send empty hash
e.logger.Debug("failed to fetch L2 head batch for status response", log.ErrKey, err)
} else {
l2HeadSeqNo = currSeqNo
}
enclaveID := e.enclaveKeyService.EnclaveID()
return common.Status{StatusCode: common.Running, L1Head: l1HeadHash, L2Head: l2HeadSeqNo, EnclaveID: enclaveID}, nil
}
func (e *enclaveInitService) Attestation(ctx context.Context) (*common.AttestationReport, common.SystemError) {
if e.enclaveKeyService.PublicKey() == nil {
return nil, responses.ToInternalError(fmt.Errorf("public key not initialized, we can't produce the attestation report"))
}
report, err := e.attestationProvider.CreateAttestationReport(ctx, e.config.HostAddress)
if err != nil {
return nil, responses.ToInternalError(fmt.Errorf("could not produce remote report. Cause %w", err))
}
return report, nil
}
// GenerateSecret - the genesis enclave is responsible with generating the secret entropy
// it returns it encrypted with the enclave key
func (e *enclaveInitService) GenerateSecret(ctx context.Context) (common.EncryptedSharedEnclaveSecret, common.SystemError) {
e.sharedSecretService.GenerateSharedSecret()
secret := e.sharedSecretService.Secret()
if secret == nil {
return nil, responses.ToInternalError(errors.New("Failed to generate secret"))
}
err := e.storage.StoreSecret(ctx, *secret)
if err != nil {
return nil, responses.ToInternalError(fmt.Errorf("could not store secret. Cause: %w", err))
}
err = e.notifyCryptoServices(*secret)
if err != nil {
return nil, responses.ToInternalError(err)
}
encSec, err := e.enclaveKeyService.Encrypt(secret[:])
if err != nil {
return nil, responses.ToInternalError(fmt.Errorf("failed to encrypt secret. Cause: %w", err))
}
return encSec, nil
}
// InitEnclave - initialise an enclave with a shared secret received from another enclave
func (e *enclaveInitService) InitEnclave(ctx context.Context, s common.EncryptedSharedEnclaveSecret) common.SystemError {
secret, err := e.enclaveKeyService.Decrypt(s)
if err != nil {
return responses.ToInternalError(err)
}
err = e.storage.StoreSecret(ctx, crypto.SharedEnclaveSecret(secret))
if err != nil {
return responses.ToInternalError(fmt.Errorf("could not store secret. Cause: %w", err))
}
var fixedSizeSecret crypto.SharedEnclaveSecret
copy(fixedSizeSecret[:], secret)
// notify the encryption services that depend on the shared secret
err = e.notifyCryptoServices(fixedSizeSecret)
if err != nil {
return responses.ToInternalError(err)
}
return nil
}
func (e *enclaveInitService) notifyCryptoServices(sharedSecret crypto.SharedEnclaveSecret) error {
e.sharedSecretService.SetSharedSecret(&sharedSecret)
err := e.rpcKeyService.Initialise()
if err != nil {
return err
}
return e.daEncryptionService.Initialise()
}
func (e *enclaveInitService) EnclaveID(context.Context) (common.EnclaveID, common.SystemError) {
return e.enclaveKeyService.EnclaveID(), nil
}
func (e *enclaveInitService) RPCEncryptionKey(ctx context.Context) ([]byte, common.SystemError) {
k, err := e.rpcKeyService.PublicKey()
if err != nil {
return nil, responses.ToInternalError(err)
}
return k, nil
}