handle worker failure condition by allowing tree production to continue

This commit is contained in:
Cassandra Heart 2025-01-10 12:15:56 -06:00
parent b764b46ac0
commit 04452e28ff
No known key found for this signature in database
GPG Key ID: 6352152859385958
5 changed files with 63 additions and 20 deletions

View File

@ -43,7 +43,7 @@ func FormatVersion(version []byte) string {
}
func GetPatchNumber() byte {
return 0x00
return 0x01
}
func GetRCNumber() byte {

View File

@ -233,7 +233,7 @@ func (e *DataClockConsensusEngine) processFrame(
latestFrame *protobufs.ClockFrame,
dataFrame *protobufs.ClockFrame,
) *protobufs.ClockFrame {
e.logger.Info(
"current frame head",
zap.Uint64("frame_number", dataFrame.FrameNumber),

View File

@ -109,7 +109,7 @@ func (p *prover) generateTransfer(coin []byte) *protobufs.TokenRequest {
func (p *prover) generateSplit(addr []byte) *protobufs.TokenRequest {
payload := []byte("split")
payload = append(payload, addr...)
bi1, _ := new(big.Int).SetString("2047999999999", 10)
bi1, _ := new(big.Int).SetString("2048000000000", 10)
bi2, _ := new(big.Int).SetString("2048000000000", 10)
payload = append(payload, bi1.FillBytes(make([]byte, 32))...)
payload = append(payload, bi2.FillBytes(make([]byte, 32))...)
@ -174,6 +174,7 @@ func (p *prover) generateProof(
proofTree *merkletree.MerkleTree,
breakWesoProof bool,
breakTreeProof bool,
treeRecovery bool,
) (*merkletree.MerkleTree, [][]byte, *protobufs.TokenRequest) {
challenge := []byte{}
challenge = append(challenge, []byte(p.peerId)...)
@ -182,7 +183,11 @@ func (p *prover) generateProof(
frame.FrameNumber,
)
outs := []merkletree.DataBlock{}
for i := 0; i < 64; i++ {
target := 8
if treeRecovery {
target = 4
}
for i := 0; i < target; i++ {
individualChallenge := append([]byte{}, challenge...)
individualChallenge = binary.BigEndian.AppendUint32(
individualChallenge,
@ -314,7 +319,7 @@ func TestHandleProverJoin(t *testing.T) {
proofTrees := []*merkletree.MerkleTree{}
reqs := []*protobufs.TokenRequest{}
for _, prover := range provers {
proofTree, _, req := prover.generateProof(frame2, wprover, nil, false, false)
proofTree, _, req := prover.generateProof(frame2, wprover, nil, false, false, false)
proofTrees = append(proofTrees, proofTree)
reqs = append(reqs, req)
}
@ -363,7 +368,7 @@ func TestHandleProverJoin(t *testing.T) {
txn.Commit()
for i, prover := range provers {
proofTree, _, req := prover.generateProof(frame3, wprover, proofTrees[i], false, false)
proofTree, _, req := prover.generateProof(frame3, wprover, proofTrees[i], false, false, true)
proofTrees[i] = proofTree
reqs[i] = req
}
@ -407,7 +412,7 @@ func TestHandleProverJoin(t *testing.T) {
err = txn.Commit()
assert.NoError(t, err)
assert.Len(t, success.Requests, 1)
assert.Len(t, app.TokenOutputs.Outputs, 3)
assert.Len(t, app.TokenOutputs.Outputs, 2)
txn, _ = app.ClockStore.NewTransaction(false)
frame4, _ := wprover.ProveDataClockFrame(frame3, [][]byte{}, []*protobufs.InclusionAggregateProof{}, bprivKey, time.Now().UnixMilli(), 10000)
@ -417,7 +422,7 @@ func TestHandleProverJoin(t *testing.T) {
txn.Commit()
for i, prover := range provers {
proofTree, _, req := prover.generateProof(frame4, wprover, proofTrees[i], false, false)
proofTree, _, req := prover.generateProof(frame4, wprover, proofTrees[i], false, false, true)
proofTrees[i] = proofTree
reqs[i] = req
}

View File

@ -59,12 +59,7 @@ func PackOutputIntoPayloadAndProof(
binary.BigEndian.AppendUint64([]byte{}, frame.FrameNumber),
}
if previousTree != nil {
// don't let node produce invalid proofs that would otherwise fail
if len(previousTree.Proofs) != modulo {
return nil, nil, errors.Wrap(errors.New("invalid tree size"), "pack output into payload and proof")
}
if previousTree != nil && len(previousTree.Proofs) == modulo {
hash := sha3.Sum256(frame.Output)
pick := BytesToUnbiasedMod(hash, uint64(modulo))
if uint64(modulo) < pick {
@ -119,12 +114,7 @@ func PackOutputIntoMultiPayloadAndProof(
binary.BigEndian.AppendUint64([]byte{}, frame.FrameNumber),
}
if previousTree != nil {
// don't let node produce invalid proofs that would otherwise fail
if len(previousTree.Proofs) != modulo {
return nil, nil, errors.Wrap(errors.New("invalid tree size"), "pack output into payload and proof")
}
if previousTree != nil && len(previousTree.Proofs) == modulo {
hash := sha3.Sum256(append(append([]byte{}, frame.Output...), previousTree.Root...))
pick := BytesToUnbiasedMod(hash, uint64(modulo))
if uint64(modulo) < pick {

View File

@ -298,3 +298,51 @@ func TestPackAndVerifyMultiOutput(t *testing.T) {
})
}
}
func TestPackAndVerifyOutputFailover(t *testing.T) {
outputs := make([]mt.DataBlock, 3)
for i := range outputs {
data := make([]byte, 32)
binary.BigEndian.PutUint32(data, uint32(i))
outputs[i] = tries.NewProofLeaf(data)
}
frame := &protobufs.ClockFrame{
FrameNumber: 1,
Output: make([]byte, 516),
}
rand.Read(frame.Output)
var previousTree *mt.MerkleTree
prevOutputs := make([]mt.DataBlock, 4)
for i := range prevOutputs {
data := make([]byte, 32)
binary.BigEndian.PutUint32(data, uint32(i))
prevOutputs[i] = tries.NewProofLeaf(data)
}
var err error
previousTree, err = mt.New(
&mt.Config{
HashFunc: func(data []byte) ([]byte, error) {
hash := sha3.Sum256(data)
return hash[:], nil
},
Mode: mt.ModeProofGen,
DisableLeafHashing: true,
},
prevOutputs,
)
require.NoError(t, err)
tree, output, err := tries.PackOutputIntoMultiPayloadAndProof(
outputs,
3,
frame,
previousTree,
)
require.NoError(t, err)
require.NotNil(t, tree)
require.NotEmpty(t, output)
require.Len(t, output, 3)
}