Skip to content

Commit 84177b7

Browse files
authored
Merge pull request #444 from bane-labs/zk-dkg
consensus/dbft: add a new goroutine for ZK proof generation
2 parents 22ba65d + 149b327 commit 84177b7

File tree

64 files changed

+1327
-346
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1327
-346
lines changed

Makefile

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ MAIN_DIR = ./privnet
1212
SINGLE_DIR = $(MAIN_DIR)/single
1313
FOUR_DIR = $(MAIN_DIR)/four
1414
SEVEN_DIR = $(MAIN_DIR)/seven
15+
ZK_DIR = $(MAIN_DIR)/zk
1516

1617
BOOTNODE = bootnode
1718
BOOTNODE_PORT = 30304
@@ -84,6 +85,10 @@ define run_bootnode
8485
-verbosity $(BOOTNODE_LOGLEVEL) > $(1)/$(BOOTNODE)/bootnode.log 2>&1 &
8586
endef
8687

88+
define run_miner_node_with_zk_dkg
89+
$(call run_node,$(1),$(2),$(3),$(4),$(5),$(6),--mine --miner.etherbase="0x$$(cat $(1)/$(7)/node_address.txt)" --antimev.password=$(1)/$(7)/password.txt --dkg.one-msg-r1cs=$(1)/r1cs/R1CS_1 --dkg.two-msg-r1cs=$(1)/r1cs/R1CS_2 --dkg.seven-msg-r1cs=$(1)/r1cs/R1CS_7 --dkg.one-msg-pk=$(1)/provingkey/PK_1 --dkg.two-msg-pk=$(1)/provingkey/PK_2 --dkg.seven-msg-pk=$(1)/provingkey/PK_7)
90+
endef
91+
8792
define run_miner_node
8893
$(call run_node,$(1),$(2),$(3),$(4),$(5),$(6),--mine --miner.etherbase="0x$$(cat $(1)/$(7)/node_address.txt)" --antimev.password=$(1)/$(7)/password.txt)
8994
endef
@@ -239,6 +244,42 @@ $(SEVEN_DIR)/$(NODE8)/geth:
239244
@echo "Initializing $(NODE8) (seed) from genesis"
240245
$(call init_node,$(SEVEN_DIR),$(NODE8))
241246

247+
$(ZK_DIR)/$(NODE0)/geth:
248+
@echo "Initializing $(NODE0) (watch-only CN) from genesis"
249+
$(call init_node,$(ZK_DIR),$(NODE0))
250+
251+
$(ZK_DIR)/$(NODE1)/geth:
252+
@echo "Initializing $(NODE1) (CN) from genesis"
253+
$(call init_node,$(ZK_DIR),$(NODE1))
254+
255+
$(ZK_DIR)/$(NODE2)/geth:
256+
@echo "Initializing $(NODE2) (CN) from genesis"
257+
$(call init_node,$(ZK_DIR),$(NODE2))
258+
259+
$(ZK_DIR)/$(NODE3)/geth:
260+
@echo "Initializing $(NODE3) (CN) from genesis"
261+
$(call init_node,$(ZK_DIR),$(NODE3))
262+
263+
$(ZK_DIR)/$(NODE4)/geth:
264+
@echo "Initializing $(NODE4) (CN) from genesis"
265+
$(call init_node,$(ZK_DIR),$(NODE4))
266+
267+
$(ZK_DIR)/$(NODE5)/geth:
268+
@echo "Initializing $(NODE5) (CN) from genesis"
269+
$(call init_node,$(ZK_DIR),$(NODE5))
270+
271+
$(ZK_DIR)/$(NODE6)/geth:
272+
@echo "Initializing $(NODE6) (CN) from genesis"
273+
$(call init_node,$(ZK_DIR),$(NODE6))
274+
275+
$(ZK_DIR)/$(NODE7)/geth:
276+
@echo "Initializing $(NODE7) (CN) from genesis"
277+
$(call init_node,$(ZK_DIR),$(NODE7))
278+
279+
$(ZK_DIR)/$(NODE8)/geth:
280+
@echo "Initializing $(NODE8) (seed) from genesis"
281+
$(call init_node,$(ZK_DIR),$(NODE8))
282+
242283
privnet_start: $(SINGLE_DIR)/$(NODE0)/geth $(SINGLE_DIR)/$(NODE1)/geth $(SINGLE_DIR)/$(NODE2)/geth
243284
@echo "Starting nodes..."
244285
$(call run_bootnode,$(SINGLE_DIR))
@@ -272,6 +313,20 @@ privnet_start_seven: $(SEVEN_DIR)/$(NODE0)/geth $(SEVEN_DIR)/$(NODE1)/geth $(SEV
272313
$(call run_node,$(SEVEN_DIR),$(NODE8),$(NODE8_PORT),$(NODE8_AUTH_PORT),$(NODE8_HTTP_PORT),$(NODE8_WS_PORT))
273314
@echo "OK! Check logs in $(SEVEN_DIR)/<node_dir>/geth_node.log"
274315

316+
privnet_start_zk: $(ZK_DIR)/$(NODE0)/geth $(ZK_DIR)/$(NODE1)/geth $(ZK_DIR)/$(NODE2)/geth $(ZK_DIR)/$(NODE3)/geth $(ZK_DIR)/$(NODE4)/geth $(ZK_DIR)/$(NODE5)/geth $(ZK_DIR)/$(NODE6)/geth $(ZK_DIR)/$(NODE7)/geth $(ZK_DIR)/$(NODE8)/geth
317+
@echo "Starting nodes..."
318+
$(call run_bootnode,$(ZK_DIR))
319+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE0),$(NODE0_PORT),$(NODE0_AUTH_PORT),$(NODE0_HTTP_PORT),$(NODE0_WS_PORT),$(NODE0))
320+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE1),$(NODE1_PORT),$(NODE1_AUTH_PORT),$(NODE1_HTTP_PORT),$(NODE1_WS_PORT),$(NODE1))
321+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE2),$(NODE2_PORT),$(NODE2_AUTH_PORT),$(NODE2_HTTP_PORT),$(NODE2_WS_PORT),$(NODE2))
322+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE3),$(NODE3_PORT),$(NODE3_AUTH_PORT),$(NODE3_HTTP_PORT),$(NODE3_WS_PORT),$(NODE3))
323+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE4),$(NODE4_PORT),$(NODE4_AUTH_PORT),$(NODE4_HTTP_PORT),$(NODE4_WS_PORT),$(NODE4))
324+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE5),$(NODE5_PORT),$(NODE5_AUTH_PORT),$(NODE5_HTTP_PORT),$(NODE5_WS_PORT),$(NODE5))
325+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE6),$(NODE6_PORT),$(NODE6_AUTH_PORT),$(NODE6_HTTP_PORT),$(NODE6_WS_PORT),$(NODE6))
326+
$(call run_miner_node_with_zk_dkg,$(ZK_DIR),$(NODE7),$(NODE7_PORT),$(NODE7_AUTH_PORT),$(NODE7_HTTP_PORT),$(NODE7_WS_PORT),$(NODE7))
327+
$(call run_node,$(ZK_DIR),$(NODE8),$(NODE8_PORT),$(NODE8_AUTH_PORT),$(NODE8_HTTP_PORT),$(NODE8_WS_PORT))
328+
@echo "OK! Check logs in $(ZK_DIR)/<node_dir>/geth_node.log"
329+
275330
docker_privnet_start:
276331
docker compose -f .docker/docker-compose.yml up -d
277332

antimev/keygroup.go

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"errors"
66
"math/big"
77

8-
"github.com/bane-labs/zk-dkg/encryption"
9-
"github.com/ethereum/go-ethereum/crypto/ecies"
108
"github.com/ethereum/go-ethereum/crypto/tpke"
119
)
1210

@@ -72,12 +70,12 @@ func (tkg *thresholdKeyGroup) copy() *thresholdKeyGroup {
7270
}
7371

7472
// prepare generates local secrets and returns sharing messages.
75-
func (tkg *thresholdKeyGroup) prepare(threshold int, messagePubKeys []*ecies.PublicKey) ([][]byte, *tpke.PVSS, error) {
73+
func (tkg *thresholdKeyGroup) prepare(size int, threshold int) ([]*big.Int, *tpke.PVSS) {
7674
// Generate local secret
7775
secret := tpke.RandomSecret(threshold)
7876
tkg.pendingSecrets = append(tkg.pendingSecrets, secret)
7977
// Generate and encrypt messages to share the secret
80-
return generateShareMessages(secret, messagePubKeys)
78+
return generateShares(secret, size)
8179
}
8280

8381
// confirmSecret requires the final contract-received PVSS to confirm the secret.
@@ -114,34 +112,35 @@ func (tkg *thresholdKeyGroup) aggregate(scaler int, aggregatedCmt []byte, isRece
114112
}
115113

116114
// recover returns received shared secrets with different message encryption.
117-
func (tkg *thresholdKeyGroup) recover(secretIndexs []int, receiverEthPubKeys []*ecies.PublicKey) ([][]byte, error) {
115+
func (tkg *thresholdKeyGroup) recover(secretIndexs []int) ([]*big.Int, error) {
118116
// Generate message
119-
srms := make([][]byte, len(secretIndexs))
117+
ss := make([]*big.Int, len(secretIndexs))
120118
for i, index := range secretIndexs {
121119
arrIndex := index - 1
122120
if tkg.receivedSecrets[arrIndex] == nil {
123121
return nil, ErrUnrecoverable
124122
}
125-
srms[i] = encryptShareMessage(receiverEthPubKeys[i], tkg.receivedSecrets[arrIndex].Bytes())
123+
ss[i] = tkg.receivedSecrets[arrIndex]
126124
}
127125

128-
return srms, nil
126+
return ss, nil
129127
}
130128

131129
// reshare does almost the same as dkgPrepare, but local secret is reused to
132130
// produce the same global public key.
133-
func (tkg *thresholdKeyGroup) reshare(messagePubKeys []*ecies.PublicKey) ([][]byte, *tpke.PVSS, error) {
131+
func (tkg *thresholdKeyGroup) reshare(size int) ([]*big.Int, *tpke.PVSS, error) {
134132
// Check if has a local secret
135133
if tkg.localSecret == nil {
136134
return nil, nil, ErrNoSecretToReshare
137135
}
138136
// Generate and encrypt messages to share the secret
139-
return generateShareMessages(tkg.localSecret.Renovate(), messagePubKeys)
137+
ss, pvss := generateShares(tkg.localSecret.Renovate(), size)
138+
return ss, pvss, nil
140139
}
141140

142141
// reshareRecovered tries to recover a dkg secret, and returns an error if
143142
// the attempt fails when shares are not enough.
144-
func (tkg *thresholdKeyGroup) reshareRecovered(threshold int, messagePubKeys []*ecies.PublicKey) ([][]byte, *tpke.PVSS, error) {
143+
func (tkg *thresholdKeyGroup) reshareRecovered(size int, threshold int) ([]*big.Int, *tpke.PVSS, error) {
145144
// Collect all shares
146145
is := make([]int, 0)
147146
fis := make([]*big.Int, 0)
@@ -156,37 +155,17 @@ func (tkg *thresholdKeyGroup) reshareRecovered(threshold int, messagePubKeys []*
156155
}
157156
// Recover the secret
158157
tkg.localSecret = tpke.RecoverSecret(is[:threshold], fis[:threshold])
159-
return tkg.reshare(messagePubKeys)
158+
return tkg.reshare(size)
160159
}
161160

162-
// generateShareMessages generates secret sharing messages.
161+
// generateShares generates shares from a secret.
163162
// Secret shares can be decrypted by specific receivers, but pvss is public.
164-
func generateShareMessages(secret *tpke.Secret, messagePubkeys []*ecies.PublicKey) ([][]byte, *tpke.PVSS, error) {
163+
func generateShares(secret *tpke.Secret, size int) ([]*big.Int, *tpke.PVSS) {
165164
// Random value for pvss generation
166165
randR := randScalar()
167-
size := len(messagePubkeys)
168166
pvss, ss := tpke.GenerateSecretShares(randR, size, secret)
169-
// Generate message
170-
messages := make([][]byte, size)
171-
for i, key := range messagePubkeys {
172-
if key == nil {
173-
return nil, nil, ErrInvalidMessageKey
174-
}
175-
messages[i] = encryptShareMessage(key, ss[i].Bytes())
176-
}
177-
178-
return messages, pvss, nil
179-
}
180167

181-
func encryptShareMessage(pub *ecies.PublicKey, share []byte) []byte {
182-
nonce, ess, _, bigR := encryption.ECIESEncrypt(pub, share)
183-
bigRBytes := bigR.RawBytes()
184-
// len(message)=64+12+len(ess)
185-
msg := make([]byte, 0)
186-
msg = append(msg, bigRBytes[:]...)
187-
msg = append(msg, nonce...)
188-
msg = append(msg, ess...)
189-
return msg
168+
return ss, pvss
190169
}
191170

192171
// receiveShareMessage verifies received sharing messages. It verifies shared

antimev/keystore.go

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -220,77 +220,54 @@ func (ks *KeyStore) OnRecoverPeriodStart() {
220220
ks.recovering = newThresholdKeyGroup(ks.size)
221221
}
222222

223-
// DKGReshare generates and returns resharing messages and pvss. The input key
224-
// array should be ordered by DKG index, e.g. keystore will use 1 as the index
225-
// to generate a reshare message for messagePubKeys[0].
226-
func (ks *KeyStore) DKGReshare(messagePubKeys []*ecies.PublicKey) ([][]byte, []byte, error) {
223+
// DKGReshare generates and returns resharing secrets and pvss.
224+
func (ks *KeyStore) DKGReshare() ([]*big.Int, []byte, error) {
227225
if ks.shared == nil {
228226
return nil, nil, ErrKeyGroupNotExists
229227
}
230-
if len(messagePubKeys) != ks.size {
231-
return nil, nil, ErrInvalidLength
232-
}
233-
// Generate secret resharing messages and pvss
234-
rMsgs, rPvss, err := ks.shared.reshare(messagePubKeys)
228+
// Generate secret resharing secrets and pvss
229+
rss, rPvss, err := ks.shared.reshare(ks.size)
235230
if err != nil {
236231
return nil, nil, err
237232
}
238233
// No data changed so no need to persist
239-
return rMsgs, rPvss.Encode(), nil
234+
return rss, rPvss.Encode(), nil
240235
}
241236

242-
// DKGShare generates and returns sharing messages and pvss. The input key array
243-
// should be ordered by DKG index, e.g. keystore will use 1 as the index to
244-
// generate a share message for messagePubKeys[0].
245-
func (ks *KeyStore) DKGShare(messagePubKeys []*ecies.PublicKey) ([][]byte, []byte, error) {
237+
// DKGShare generates and returns sharing secrets and pvss.
238+
func (ks *KeyStore) DKGShare() ([]*big.Int, []byte, error) {
246239
if ks.sharing == nil {
247240
return nil, nil, ErrKeyGroupNotExists
248241
}
249-
if len(messagePubKeys) != ks.size {
250-
return nil, nil, ErrInvalidLength
251-
}
252-
// Generate secret sharing messages and pvss
253-
sMsgs, sPvss, err := ks.sharing.prepare(ks.threshold, messagePubKeys)
254-
if err != nil {
255-
return nil, nil, err
256-
}
257-
return sMsgs, sPvss.Encode(), nil
242+
// Generate sharing secrets and pvss
243+
ss, sPvss := ks.sharing.prepare(ks.size, ks.threshold)
244+
return ss, sPvss.Encode(), nil
258245
}
259246

260-
// DKGRecover generates and returns recovering messages and pvss. The input index
261-
// should be a DKG index starts from 1, and the size of two inputs should be the
262-
// same.
263-
func (ks *KeyStore) DKGRecover(indexes []int, messagePubKeys []*ecies.PublicKey) ([][]byte, error) {
247+
// DKGRecover generates and returns recovering secrets and pvss.
248+
func (ks *KeyStore) DKGRecover(indexes []int) ([]*big.Int, error) {
264249
if ks.shared == nil {
265250
return nil, ErrKeyGroupNotExists
266251
}
267-
if len(indexes) != len(messagePubKeys) {
268-
return nil, ErrLengthMismatch
269-
}
270-
if len(messagePubKeys) < 1 {
271-
return nil, ErrNoNeedToRecover
272-
}
273-
if len(messagePubKeys) > ks.size-ks.threshold {
252+
if len(indexes) > ks.size-ks.threshold {
274253
return nil, ErrUnrecoverable
275254
}
276-
// Generate secret recovering messages
277-
return ks.shared.recover(indexes, messagePubKeys)
255+
// Generate recovering secrets
256+
return ks.shared.recover(indexes)
278257
}
279258

280-
// TryRecoverReshare tries to recover a resharing message, should be called when
281-
// resharing fails and receives a recover message. It returns resharing messages
282-
// immediately if recoverd, otherwise an error. The input key array should be
283-
// ordered by DKG index, e.g. keystore will use 1 as the index to generate a
284-
// share message for messagePubKeys[0].
285-
func (ks *KeyStore) TryRecoverReshare(messagePubKeys []*ecies.PublicKey) ([][]byte, []byte, error) {
259+
// TryRecoverReshare tries to recover a local secret, should be called when
260+
// resharing fails and receives a recover message. It returns resharing secrets
261+
// immediately if recoverd, otherwise an error.
262+
func (ks *KeyStore) TryRecoverReshare() ([]*big.Int, []byte, error) {
286263
if ks.recovering == nil {
287264
return nil, nil, ErrKeyGroupNotExists
288265
}
289-
msgs, pvss, err := ks.recovering.reshareRecovered(ks.threshold, messagePubKeys)
266+
ss, pvss, err := ks.recovering.reshareRecovered(ks.size, ks.threshold)
290267
if err != nil {
291268
return nil, nil, err
292269
}
293-
return msgs, pvss.Encode(), nil
270+
return ss, pvss.Encode(), nil
294271
}
295272

296273
// RevertRound reverts all progress of current round of DKG.

0 commit comments

Comments
 (0)