From 29d9bf5273098f90abe864ce08cf87e30dc30a26 Mon Sep 17 00:00:00 2001 From: Christopher Tarry Date: Thu, 29 Aug 2024 17:09:21 -0400 Subject: [PATCH 1/3] add v2 apply/revert test with siacoin, siafund, file contract, file contract revisions --- consensus/update_test.go | 417 ++++++++++++++++++++++++++++++++++- consensus/validation_test.go | 40 +++- 2 files changed, 450 insertions(+), 7 deletions(-) diff --git a/consensus/update_test.go b/consensus/update_test.go index b5f3dc7f..ffb3b180 100644 --- a/consensus/update_test.go +++ b/consensus/update_test.go @@ -476,7 +476,7 @@ func TestRevertedRevisionLeaf(t *testing.T) { } } -func TestApplyRevertBlock(t *testing.T) { +func TestApplyRevertBlockV1(t *testing.T) { n, genesisBlock := testnet() giftPrivateKey := types.GeneratePrivateKey() @@ -853,3 +853,418 @@ func TestApplyRevertBlock(t *testing.T) { checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) } } + +func TestApplyRevertBlockV2(t *testing.T) { + n, genesisBlock := testnet() + n.HardforkV2.AllowHeight = 1 + n.HardforkV2.RequireHeight = 2 + + giftPrivateKey := types.GeneratePrivateKey() + giftPublicKey := giftPrivateKey.PublicKey() + + renterPrivateKey := types.GeneratePrivateKey() + renterPublicKey := renterPrivateKey.PublicKey() + + hostPrivateKey := types.GeneratePrivateKey() + hostPublicKey := hostPrivateKey.PublicKey() + + giftAddress := types.StandardUnlockHash(giftPublicKey) + giftAmountSC := types.Siacoins(100) + giftAmountSF := uint64(100) + giftTxn := types.Transaction{ + SiacoinOutputs: []types.SiacoinOutput{ + {Address: giftAddress, Value: giftAmountSC}, + }, + SiafundOutputs: []types.SiafundOutput{ + {Address: giftAddress, Value: giftAmountSF}, + }, + } + genesisBlock.Transactions = []types.Transaction{giftTxn} + db, cs := newConsensusDB(n, genesisBlock) + + signTxn := func(cs State, txn *types.V2Transaction) { + for i := range txn.SiacoinInputs { + txn.SiacoinInputs[i].SatisfiedPolicy.Signatures = []types.Signature{giftPrivateKey.SignHash(cs.InputSigHash(*txn))} + } + for i := range txn.SiafundInputs { + txn.SiafundInputs[i].SatisfiedPolicy.Signatures = []types.Signature{giftPrivateKey.SignHash(cs.InputSigHash(*txn))} + } + for i := range txn.FileContracts { + txn.FileContracts[i].RenterSignature = renterPrivateKey.SignHash(cs.ContractSigHash(txn.FileContracts[i])) + txn.FileContracts[i].HostSignature = hostPrivateKey.SignHash(cs.ContractSigHash(txn.FileContracts[i])) + } + for i := range txn.FileContractRevisions { + txn.FileContractRevisions[i].Revision.RenterSignature = renterPrivateKey.SignHash(cs.ContractSigHash(txn.FileContractRevisions[i].Revision)) + txn.FileContractRevisions[i].Revision.HostSignature = hostPrivateKey.SignHash(cs.ContractSigHash(txn.FileContractRevisions[i].Revision)) + } + for i := range txn.FileContractResolutions { + switch r := txn.FileContractResolutions[i].Resolution.(type) { + case *types.V2FileContractRenewal: + r.RenterSignature = renterPrivateKey.SignHash(cs.RenewalSigHash(*r)) + r.HostSignature = hostPrivateKey.SignHash(cs.RenewalSigHash(*r)) + case *types.V2FileContractFinalization: + r.RenterSignature = renterPrivateKey.SignHash(cs.ContractSigHash(types.V2FileContract(*r))) + r.HostSignature = hostPrivateKey.SignHash(cs.ContractSigHash(types.V2FileContract(*r))) + } + } + } + addBlock := func(b *types.Block, bs V1BlockSupplement) (au ApplyUpdate, err error) { + if b.V2 != nil { + b.V2.Commitment = cs.Commitment(cs.TransactionsCommitment(b.Transactions, b.V2Transactions()), b.MinerPayouts[0].Address) + } + findBlockNonce(cs, b) + if err = ValidateBlock(cs, *b, bs); err != nil { + return + } + cs, au = ApplyBlock(cs, *b, bs, db.ancestorTimestamp(b.ParentID)) + db.applyBlock(au) + return + } + checkUpdateElements := func(au ApplyUpdate, addedSCEs, spentSCEs []types.SiacoinElement, addedSFEs, spentSFEs []types.SiafundElement) { + au.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) { + sces := &addedSCEs + if spent { + sces = &spentSCEs + } + if len(*sces) == 0 { + t.Fatal("unexpected spent siacoin element") + } + sce.StateElement = types.StateElement{} + if !reflect.DeepEqual(sce, (*sces)[0]) { + t.Fatalf("siacoin element doesn't match:\n%v\nvs\n%v\n", sce, (*sces)[0]) + } + *sces = (*sces)[1:] + }) + au.ForEachSiafundElement(func(sfe types.SiafundElement, created, spent bool) { + sfes := &addedSFEs + if spent { + sfes = &spentSFEs + } + if len(*sfes) == 0 { + t.Fatal("unexpected spent siafund element") + } + sfe.StateElement = types.StateElement{} + if !reflect.DeepEqual(sfe, (*sfes)[0]) { + t.Fatalf("siafund element doesn't match:\n%v\nvs\n%v\n", sfe, (*sfes)[0]) + } + *sfes = (*sfes)[1:] + }) + if len(addedSCEs)+len(spentSCEs)+len(addedSFEs)+len(spentSFEs) > 0 { + t.Fatal("extraneous elements") + } + } + checkRevertElements := func(ru RevertUpdate, addedSCEs, spentSCEs []types.SiacoinElement, addedSFEs, spentSFEs []types.SiafundElement) { + ru.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) { + sces := &addedSCEs + if spent { + sces = &spentSCEs + } + if len(*sces) == 0 { + t.Fatal("unexpected spent siacoin element") + } + sce.StateElement = types.StateElement{} + if !reflect.DeepEqual(sce, (*sces)[len(*sces)-1]) { + t.Fatalf("siacoin element doesn't match:\n%v\nvs\n%v\n", sce, (*sces)[len(*sces)-1]) + } + *sces = (*sces)[:len(*sces)-1] + }) + ru.ForEachSiafundElement(func(sfe types.SiafundElement, created, spent bool) { + sfes := &addedSFEs + if spent { + sfes = &spentSFEs + } + if len(*sfes) == 0 { + t.Fatal("unexpected spent siafund element") + } + sfe.StateElement = types.StateElement{} + if !reflect.DeepEqual(sfe, (*sfes)[len(*sfes)-1]) { + t.Fatalf("siafund element doesn't match:\n%v\nvs\n%v\n", sfe, (*sfes)[len(*sfes)-1]) + } + *sfes = (*sfes)[:len(*sfes)-1] + }) + if len(addedSCEs)+len(spentSCEs)+len(addedSFEs)+len(spentSFEs) > 0 { + t.Fatal("extraneous elements") + } + } + satisfiedPolicy := func(uc types.UnlockConditions) types.SatisfiedPolicy { + return types.SatisfiedPolicy{ + Policy: types.SpendPolicy{types.PolicyTypeUnlockConditions(uc)}, + } + } + + // block with nothing except block reward + b1 := types.Block{ + ParentID: genesisBlock.ID(), + Timestamp: types.CurrentTimestamp(), + MinerPayouts: []types.SiacoinOutput{{Address: types.VoidAddress, Value: cs.BlockReward()}}, + } + addedSCEs := []types.SiacoinElement{ + {SiacoinOutput: b1.MinerPayouts[0], MaturityHeight: cs.MaturityHeight()}, + } + spentSCEs := []types.SiacoinElement{} + addedSFEs := []types.SiafundElement{} + spentSFEs := []types.SiafundElement{} + if au, err := addBlock(&b1, db.supplementTipBlock(b1)); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } + + // block that spends part of the gift transaction + txnB2 := types.V2Transaction{ + SiacoinInputs: []types.V2SiacoinInput{{ + Parent: db.sces[giftTxn.SiacoinOutputID(0)], + SatisfiedPolicy: satisfiedPolicy(types.StandardUnlockConditions(giftPublicKey)), + }}, + SiafundInputs: []types.V2SiafundInput{{ + Parent: db.sfes[giftTxn.SiafundOutputID(0)], + ClaimAddress: types.VoidAddress, + SatisfiedPolicy: satisfiedPolicy(types.StandardUnlockConditions(giftPublicKey)), + }}, + SiacoinOutputs: []types.SiacoinOutput{ + {Value: giftAmountSC.Div64(2), Address: giftAddress}, + {Value: giftAmountSC.Div64(2), Address: types.VoidAddress}, + }, + SiafundOutputs: []types.SiafundOutput{ + {Value: giftAmountSF / 2, Address: giftAddress}, + {Value: giftAmountSF / 2, Address: types.VoidAddress}, + }, + } + signTxn(cs, &txnB2) + b2 := types.Block{ + ParentID: b1.ID(), + Timestamp: types.CurrentTimestamp(), + MinerPayouts: []types.SiacoinOutput{{Address: types.VoidAddress, Value: cs.BlockReward()}}, + V2: &types.V2BlockData{ + Height: 2, + Transactions: []types.V2Transaction{txnB2}, + }, + } + addedSCEs = []types.SiacoinElement{ + {SiacoinOutput: txnB2.SiacoinOutputs[0]}, + {SiacoinOutput: txnB2.SiacoinOutputs[1]}, + {SiacoinOutput: types.SiacoinOutput{Value: types.ZeroCurrency, Address: txnB2.SiafundInputs[0].ClaimAddress}, MaturityHeight: cs.MaturityHeight()}, + {SiacoinOutput: b2.MinerPayouts[0], MaturityHeight: cs.MaturityHeight()}, + } + spentSCEs = []types.SiacoinElement{ + {SiacoinOutput: giftTxn.SiacoinOutputs[0]}, + } + addedSFEs = []types.SiafundElement{ + {SiafundOutput: txnB2.SiafundOutputs[0]}, + {SiafundOutput: txnB2.SiafundOutputs[1]}, + } + spentSFEs = []types.SiafundElement{ + {SiafundOutput: giftTxn.SiafundOutputs[0]}, + } + + prev := cs + bs := db.supplementTipBlock(b2) + if au, err := addBlock(&b2, bs); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } + + _ = renterPublicKey + _ = hostPublicKey + _ = checkRevertElements + _ = prev + + // revert block spending sc and sf + ru := RevertBlock(prev, b2, bs) + cs = prev + checkRevertUpdate(t, cs, ru) + checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + db.revertBlock(ru) + + // block that creates a file contract + v1FC := prepareContractFormation(renterPublicKey, hostPublicKey, types.Siacoins(1), types.Siacoins(1), 100, 105, types.VoidAddress) + v1FC.Filesize = 65 + v1FC.FileMerkleRoot = blake2b.SumPair((State{}).StorageProofLeafHash([]byte{1}), (State{}).StorageProofLeafHash([]byte{2})) + v2FC := types.V2FileContract{ + Filesize: v1FC.Filesize, + FileMerkleRoot: v1FC.FileMerkleRoot, + ProofHeight: 20, + ExpirationHeight: 30, + RenterOutput: v1FC.ValidProofOutputs[0], + HostOutput: v1FC.ValidProofOutputs[1], + MissedHostValue: v1FC.MissedProofOutputs[1].Value, + TotalCollateral: v1FC.ValidProofOutputs[0].Value, + RenterPublicKey: renterPublicKey, + HostPublicKey: hostPublicKey, + } + fcOut := v2FC.RenterOutput.Value.Add(v2FC.HostOutput.Value).Add(cs.V2FileContractTax(v2FC)) + + txnB3 := types.V2Transaction{ + SiacoinInputs: []types.V2SiacoinInput{{ + Parent: db.sces[giftTxn.SiacoinOutputID(0)], + SatisfiedPolicy: satisfiedPolicy(types.StandardUnlockConditions(giftPublicKey)), + }}, + SiacoinOutputs: []types.SiacoinOutput{{ + Address: giftAddress, + Value: giftAmountSC.Sub(fcOut), + }}, + FileContracts: []types.V2FileContract{v2FC}, + } + signTxn(cs, &txnB3) + + b3 := types.Block{ + ParentID: b1.ID(), + Timestamp: types.CurrentTimestamp(), + MinerPayouts: []types.SiacoinOutput{{Address: types.VoidAddress, Value: cs.BlockReward()}}, + V2: &types.V2BlockData{ + Height: 2, + Transactions: []types.V2Transaction{txnB3}, + }, + } + addedSCEs = []types.SiacoinElement{ + {SiacoinOutput: txnB3.SiacoinOutputs[0]}, + {SiacoinOutput: b3.MinerPayouts[0], MaturityHeight: cs.MaturityHeight()}, + } + spentSCEs = []types.SiacoinElement{ + {SiacoinOutput: giftTxn.SiacoinOutputs[0]}, + } + addedSFEs = nil + spentSFEs = nil + + // add block creating fc + bs = db.supplementTipBlock(b3) + if au, err := addBlock(&b3, bs); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } + + // revert block creating fc + ru = RevertBlock(prev, b3, bs) + cs = prev + checkRevertUpdate(t, cs, ru) + checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + db.revertBlock(ru) + + // readd block creating fc + if au, err := addBlock(&b3, bs); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } + + // block creating file contract revision + fcr := v2FC + fcr.RevisionNumber++ + fcr.Filesize = 65 + fcr.ProofHeight = 4 + fcr.ExpirationHeight = 20 + fcr.FileMerkleRoot = blake2b.SumPair((State{}).StorageProofLeafHash([]byte{1}), (State{}).StorageProofLeafHash([]byte{2})) + + txnB4 := types.V2Transaction{ + FileContractRevisions: []types.V2FileContractRevision{{ + Parent: db.v2fces[txnB3.V2FileContractID(txnB3.ID(), 0)], + Revision: fcr, + }}, + } + signTxn(cs, &txnB4) + b4 := types.Block{ + ParentID: b3.ID(), + Timestamp: types.CurrentTimestamp(), + MinerPayouts: []types.SiacoinOutput{{Address: types.VoidAddress, Value: cs.BlockReward()}}, + V2: &types.V2BlockData{ + Height: 3, + Transactions: []types.V2Transaction{txnB4}, + }, + } + addedSCEs = []types.SiacoinElement{ + {SiacoinOutput: b4.MinerPayouts[0], MaturityHeight: cs.MaturityHeight()}, + } + spentSCEs = []types.SiacoinElement{ + // {SiacoinOutput: giftTxn.SiacoinOutputs[0]}, + } + addedSFEs = nil + spentSFEs = nil + + prev = cs + bs = db.supplementTipBlock(b4) + if au, err := addBlock(&b4, bs); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } + + // revert block revising fc + ru = RevertBlock(prev, b4, bs) + cs = prev + checkRevertUpdate(t, cs, ru) + checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + db.revertBlock(ru) + + // readd block revising fc + if au, err := addBlock(&b4, bs); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } + + // // block with storage proof + // txnB5 := types.Transaction{ + // StorageProofs: []types.StorageProof{{ + // ParentID: txnB3.FileContractID(0), + // Leaf: [64]byte{1}, + // Proof: []types.Hash256{cs.StorageProofLeafHash([]byte{2})}, + // }}, + // } + // signTxn(cs, &txnB5) + // b5 := types.Block{ + // ParentID: b4.ID(), + // Timestamp: types.CurrentTimestamp(), + // MinerPayouts: []types.SiacoinOutput{{Address: types.VoidAddress, Value: cs.BlockReward()}}, + // Transactions: []types.Transaction{txnB5}, + // } + // if cs.StorageProofLeafIndex(fcr.Filesize, b3.ID(), types.FileContractID(txnB3.FileContractID(0))) == 1 { + // b5.Transactions[0].StorageProofs[0] = types.StorageProof{ + // ParentID: txnB3.FileContractID(0), + // Leaf: [64]byte{2}, + // Proof: []types.Hash256{cs.StorageProofLeafHash([]byte{1})}, + // } + // } + // addedSCEs = []types.SiacoinElement{ + // {SiacoinOutput: txnB3.FileContracts[0].ValidProofOutputs[1], MaturityHeight: 148}, + // {SiacoinOutput: txnB3.FileContracts[0].ValidProofOutputs[0], MaturityHeight: 148}, + // {SiacoinOutput: b5.MinerPayouts[0], MaturityHeight: cs.MaturityHeight()}, + // } + // spentSCEs = nil + // addedSFEs = nil + // spentSFEs = nil + + // // add block with storage proof + // bs = db.supplementTipBlock(b5) + // bs.Transactions[0].ValidFileContracts = append(bs.Transactions[0].ValidFileContracts, db.fces[txnB5.StorageProofs[0].ParentID]) + // bs.Transactions[0].StorageProofBlockIDs = append(bs.Transactions[0].StorageProofBlockIDs, b3.ID()) + // prev = cs + // if au, err := addBlock(&b5, bs); err != nil { + // t.Fatal(err) + // } else { + // checkApplyUpdate(t, cs, au) + // checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + // } + + // // revert block with storage proof + // ru = RevertBlock(prev, b5, bs) + // cs = prev + // checkRevertUpdate(t, cs, ru) + // checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + // db.revertBlock(ru) + + // // readd block with storage proof + // if au, err := addBlock(&b5, bs); err != nil { + // t.Fatal(err) + // } else { + // checkApplyUpdate(t, cs, au) + // checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + // } +} diff --git a/consensus/validation_test.go b/consensus/validation_test.go index bde0a6a1..40f37946 100644 --- a/consensus/validation_test.go +++ b/consensus/validation_test.go @@ -40,9 +40,10 @@ func testnet() (*Network, types.Block) { } type consensusDB struct { - sces map[types.SiacoinOutputID]types.SiacoinElement - sfes map[types.SiafundOutputID]types.SiafundElement - fces map[types.FileContractID]types.FileContractElement + sces map[types.SiacoinOutputID]types.SiacoinElement + sfes map[types.SiafundOutputID]types.SiafundElement + fces map[types.FileContractID]types.FileContractElement + v2fces map[types.FileContractID]types.V2FileContractElement } func (db *consensusDB) applyBlock(au ApplyUpdate) { @@ -58,6 +59,10 @@ func (db *consensusDB) applyBlock(au ApplyUpdate) { au.UpdateElementProof(&fce.StateElement) db.fces[id] = fce } + for id, fce := range db.v2fces { + au.UpdateElementProof(&fce.StateElement) + db.v2fces[id] = fce + } au.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) { if spent { delete(db.sces, types.SiacoinOutputID(sce.ID)) @@ -81,6 +86,15 @@ func (db *consensusDB) applyBlock(au ApplyUpdate) { delete(db.fces, types.FileContractID(fce.ID)) } }) + au.ForEachV2FileContractElement(func(fce types.V2FileContractElement, created bool, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) { + if created { + db.v2fces[types.FileContractID(fce.ID)] = fce + } else if rev != nil { + db.v2fces[types.FileContractID(fce.ID)] = *rev + } else if res != nil { + delete(db.v2fces, types.FileContractID(fce.ID)) + } + }) } func (db *consensusDB) revertBlock(ru RevertUpdate) { @@ -107,6 +121,15 @@ func (db *consensusDB) revertBlock(ru RevertUpdate) { db.fces[types.FileContractID(fce.ID)] = fce } }) + ru.ForEachV2FileContractElement(func(fce types.V2FileContractElement, created bool, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) { + if created { + delete(db.v2fces, types.FileContractID(fce.ID)) + } else if rev != nil { + db.v2fces[types.FileContractID(fce.ID)] = fce + } else if res != nil { + db.v2fces[types.FileContractID(fce.ID)] = fce + } + }) for id, sce := range db.sces { ru.UpdateElementProof(&sce.StateElement) db.sces[id] = sce @@ -119,6 +142,10 @@ func (db *consensusDB) revertBlock(ru RevertUpdate) { ru.UpdateElementProof(&fce.StateElement) db.fces[id] = fce } + for id, fce := range db.v2fces { + ru.UpdateElementProof(&fce.StateElement) + db.v2fces[id] = fce + } } func (db *consensusDB) supplementTipBlock(b types.Block) (bs V1BlockSupplement) { @@ -152,9 +179,10 @@ func (db *consensusDB) ancestorTimestamp(types.BlockID) time.Time { func newConsensusDB(n *Network, genesisBlock types.Block) (*consensusDB, State) { db := &consensusDB{ - sces: make(map[types.SiacoinOutputID]types.SiacoinElement), - sfes: make(map[types.SiafundOutputID]types.SiafundElement), - fces: make(map[types.FileContractID]types.FileContractElement), + sces: make(map[types.SiacoinOutputID]types.SiacoinElement), + sfes: make(map[types.SiafundOutputID]types.SiafundElement), + fces: make(map[types.FileContractID]types.FileContractElement), + v2fces: make(map[types.FileContractID]types.V2FileContractElement), } cs, au := ApplyBlock(n.GenesisState(), genesisBlock, db.supplementTipBlock(genesisBlock), time.Time{}) db.applyBlock(au) From b34aa3b21dd56f9e0fcf8328e512cdf9efe7d44b Mon Sep 17 00:00:00 2001 From: Christopher Tarry Date: Thu, 29 Aug 2024 17:43:59 -0400 Subject: [PATCH 2/3] add storage proof --- consensus/update_test.go | 150 ++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 73 deletions(-) diff --git a/consensus/update_test.go b/consensus/update_test.go index ffb3b180..cc9db804 100644 --- a/consensus/update_test.go +++ b/consensus/update_test.go @@ -908,15 +908,15 @@ func TestApplyRevertBlockV2(t *testing.T) { } } } - addBlock := func(b *types.Block, bs V1BlockSupplement) (au ApplyUpdate, err error) { + addBlock := func(b *types.Block) (au ApplyUpdate, err error) { if b.V2 != nil { b.V2.Commitment = cs.Commitment(cs.TransactionsCommitment(b.Transactions, b.V2Transactions()), b.MinerPayouts[0].Address) } findBlockNonce(cs, b) - if err = ValidateBlock(cs, *b, bs); err != nil { + if err = ValidateBlock(cs, *b, V1BlockSupplement{}); err != nil { return } - cs, au = ApplyBlock(cs, *b, bs, db.ancestorTimestamp(b.ParentID)) + cs, au = ApplyBlock(cs, *b, V1BlockSupplement{}, db.ancestorTimestamp(b.ParentID)) db.applyBlock(au) return } @@ -1004,7 +1004,7 @@ func TestApplyRevertBlockV2(t *testing.T) { spentSCEs := []types.SiacoinElement{} addedSFEs := []types.SiafundElement{} spentSFEs := []types.SiafundElement{} - if au, err := addBlock(&b1, db.supplementTipBlock(b1)); err != nil { + if au, err := addBlock(&b1); err != nil { t.Fatal(err) } else { checkApplyUpdate(t, cs, au) @@ -1059,8 +1059,7 @@ func TestApplyRevertBlockV2(t *testing.T) { } prev := cs - bs := db.supplementTipBlock(b2) - if au, err := addBlock(&b2, bs); err != nil { + if au, err := addBlock(&b2); err != nil { t.Fatal(err) } else { checkApplyUpdate(t, cs, au) @@ -1073,7 +1072,7 @@ func TestApplyRevertBlockV2(t *testing.T) { _ = prev // revert block spending sc and sf - ru := RevertBlock(prev, b2, bs) + ru := RevertBlock(prev, b2, V1BlockSupplement{}) cs = prev checkRevertUpdate(t, cs, ru) checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) @@ -1130,8 +1129,7 @@ func TestApplyRevertBlockV2(t *testing.T) { spentSFEs = nil // add block creating fc - bs = db.supplementTipBlock(b3) - if au, err := addBlock(&b3, bs); err != nil { + if au, err := addBlock(&b3); err != nil { t.Fatal(err) } else { checkApplyUpdate(t, cs, au) @@ -1139,14 +1137,14 @@ func TestApplyRevertBlockV2(t *testing.T) { } // revert block creating fc - ru = RevertBlock(prev, b3, bs) + ru = RevertBlock(prev, b3, V1BlockSupplement{}) cs = prev checkRevertUpdate(t, cs, ru) checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) db.revertBlock(ru) // readd block creating fc - if au, err := addBlock(&b3, bs); err != nil { + if au, err := addBlock(&b3); err != nil { t.Fatal(err) } else { checkApplyUpdate(t, cs, au) @@ -1157,7 +1155,7 @@ func TestApplyRevertBlockV2(t *testing.T) { fcr := v2FC fcr.RevisionNumber++ fcr.Filesize = 65 - fcr.ProofHeight = 4 + fcr.ProofHeight = 3 fcr.ExpirationHeight = 20 fcr.FileMerkleRoot = blake2b.SumPair((State{}).StorageProofLeafHash([]byte{1}), (State{}).StorageProofLeafHash([]byte{2})) @@ -1186,85 +1184,91 @@ func TestApplyRevertBlockV2(t *testing.T) { addedSFEs = nil spentSFEs = nil + var cie types.ChainIndexElement prev = cs - bs = db.supplementTipBlock(b4) - if au, err := addBlock(&b4, bs); err != nil { + if au, err := addBlock(&b4); err != nil { t.Fatal(err) } else { + cie = au.ChainIndexElement() checkApplyUpdate(t, cs, au) checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) } // revert block revising fc - ru = RevertBlock(prev, b4, bs) + ru = RevertBlock(prev, b4, V1BlockSupplement{}) cs = prev checkRevertUpdate(t, cs, ru) checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) db.revertBlock(ru) // readd block revising fc - if au, err := addBlock(&b4, bs); err != nil { + if au, err := addBlock(&b4); err != nil { t.Fatal(err) } else { checkApplyUpdate(t, cs, au) checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) } - // // block with storage proof - // txnB5 := types.Transaction{ - // StorageProofs: []types.StorageProof{{ - // ParentID: txnB3.FileContractID(0), - // Leaf: [64]byte{1}, - // Proof: []types.Hash256{cs.StorageProofLeafHash([]byte{2})}, - // }}, - // } - // signTxn(cs, &txnB5) - // b5 := types.Block{ - // ParentID: b4.ID(), - // Timestamp: types.CurrentTimestamp(), - // MinerPayouts: []types.SiacoinOutput{{Address: types.VoidAddress, Value: cs.BlockReward()}}, - // Transactions: []types.Transaction{txnB5}, - // } - // if cs.StorageProofLeafIndex(fcr.Filesize, b3.ID(), types.FileContractID(txnB3.FileContractID(0))) == 1 { - // b5.Transactions[0].StorageProofs[0] = types.StorageProof{ - // ParentID: txnB3.FileContractID(0), - // Leaf: [64]byte{2}, - // Proof: []types.Hash256{cs.StorageProofLeafHash([]byte{1})}, - // } - // } - // addedSCEs = []types.SiacoinElement{ - // {SiacoinOutput: txnB3.FileContracts[0].ValidProofOutputs[1], MaturityHeight: 148}, - // {SiacoinOutput: txnB3.FileContracts[0].ValidProofOutputs[0], MaturityHeight: 148}, - // {SiacoinOutput: b5.MinerPayouts[0], MaturityHeight: cs.MaturityHeight()}, - // } - // spentSCEs = nil - // addedSFEs = nil - // spentSFEs = nil - - // // add block with storage proof - // bs = db.supplementTipBlock(b5) - // bs.Transactions[0].ValidFileContracts = append(bs.Transactions[0].ValidFileContracts, db.fces[txnB5.StorageProofs[0].ParentID]) - // bs.Transactions[0].StorageProofBlockIDs = append(bs.Transactions[0].StorageProofBlockIDs, b3.ID()) - // prev = cs - // if au, err := addBlock(&b5, bs); err != nil { - // t.Fatal(err) - // } else { - // checkApplyUpdate(t, cs, au) - // checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) - // } - - // // revert block with storage proof - // ru = RevertBlock(prev, b5, bs) - // cs = prev - // checkRevertUpdate(t, cs, ru) - // checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) - // db.revertBlock(ru) - - // // readd block with storage proof - // if au, err := addBlock(&b5, bs); err != nil { - // t.Fatal(err) - // } else { - // checkApplyUpdate(t, cs, au) - // checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) - // } + // block with storage proof + fce := db.v2fces[txnB3.V2FileContractID(txnB3.ID(), 0)] + txnB5 := types.V2Transaction{ + FileContractResolutions: []types.V2FileContractResolution{{ + Parent: fce, + Resolution: &types.V2StorageProof{ + ProofIndex: cie, + Leaf: [64]byte{1}, + Proof: []types.Hash256{cs.StorageProofLeafHash([]byte{2})}, + }, + }}, + } + signTxn(cs, &txnB5) + b5 := types.Block{ + ParentID: b4.ID(), + Timestamp: types.CurrentTimestamp(), + MinerPayouts: []types.SiacoinOutput{{Address: types.VoidAddress, Value: cs.BlockReward()}}, + V2: &types.V2BlockData{ + Height: 4, + Transactions: []types.V2Transaction{txnB5}, + }, + } + if cs.StorageProofLeafIndex(fce.V2FileContract.Filesize, cie.ChainIndex.ID, types.FileContractID(fce.ID)) == 1 { + b5.V2.Transactions[0].FileContractResolutions[0].Resolution = &types.V2StorageProof{ + ProofIndex: cie, + Leaf: [64]byte{2}, + Proof: []types.Hash256{cs.StorageProofLeafHash([]byte{1})}, + } + } + + addedSCEs = []types.SiacoinElement{ + {SiacoinOutput: txnB3.FileContracts[0].RenterOutput, MaturityHeight: 148}, + {SiacoinOutput: txnB3.FileContracts[0].HostOutput, MaturityHeight: 148}, + {SiacoinOutput: b5.MinerPayouts[0], MaturityHeight: cs.MaturityHeight()}, + } + spentSCEs = nil + addedSFEs = nil + spentSFEs = nil + + // add block with storage proof + prev = cs + if au, err := addBlock(&b5); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } + + // revert block with storage proof + ru = RevertBlock(prev, b5, V1BlockSupplement{}) + cs = prev + checkRevertUpdate(t, cs, ru) + checkRevertElements(ru, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + db.revertBlock(ru) + + // readd block with storage proof + if au, err := addBlock(&b5); err != nil { + t.Fatal(err) + } else { + checkApplyUpdate(t, cs, au) + checkUpdateElements(au, addedSCEs, spentSCEs, addedSFEs, spentSFEs) + } } From 03be3b2fb889584b84647ad1e505c1236b5e4516 Mon Sep 17 00:00:00 2001 From: Christopher Tarry Date: Thu, 29 Aug 2024 17:46:07 -0400 Subject: [PATCH 3/3] fix lint --- consensus/update_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/update_test.go b/consensus/update_test.go index cc9db804..cbe8dab7 100644 --- a/consensus/update_test.go +++ b/consensus/update_test.go @@ -988,7 +988,7 @@ func TestApplyRevertBlockV2(t *testing.T) { } satisfiedPolicy := func(uc types.UnlockConditions) types.SatisfiedPolicy { return types.SatisfiedPolicy{ - Policy: types.SpendPolicy{types.PolicyTypeUnlockConditions(uc)}, + Policy: types.SpendPolicy{Type: types.PolicyTypeUnlockConditions(uc)}, } }