Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into nate/rhp4
Browse files Browse the repository at this point in the history
  • Loading branch information
n8maninger committed Oct 21, 2024
2 parents e48286d + cc3bde7 commit efc26ef
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 71 deletions.
2 changes: 1 addition & 1 deletion consensus/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ func (ms *MidState) ApplyV2Transaction(txn types.V2Transaction) {
case *types.V2StorageProof:
renter, host = fc.RenterOutput, fc.HostOutput
case *types.V2FileContractFinalization:
renter, host = r.RenterOutput, r.HostOutput
renter, host = fc.RenterOutput, fc.HostOutput
case *types.V2FileContractExpiration:
renter, host = fc.RenterOutput, fc.MissedHostOutput()
}
Expand Down
3 changes: 1 addition & 2 deletions consensus/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -905,8 +905,7 @@ func TestApplyRevertBlockV2(t *testing.T) {
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)))
*r = types.V2FileContractFinalization(renterPrivateKey.SignHash(cs.ContractSigHash(txn.FileContractResolutions[i].Parent.V2FileContract)))
}
}
}
Expand Down
52 changes: 22 additions & 30 deletions consensus/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func validateMinerPayouts(s State, b types.Block) error {
for _, txn := range b.V2.Transactions {
expectedSum, overflow = expectedSum.AddWithOverflow(txn.MinerFee)
if overflow {
return errors.New("transaction fees overflow")
return errors.New("v2 transaction fees overflow")
}
}
if len(b.MinerPayouts) != 1 {
Expand Down Expand Up @@ -509,7 +509,7 @@ func ValidateTransaction(ms *MidState, txn types.Transaction, ts V1TransactionSu
return nil
}

func validateV2CurrencyValues(ms *MidState, txn types.V2Transaction) error {
func validateV2CurrencyOverflow(ms *MidState, txn types.V2Transaction) error {
// Add up all of the currency values in the transaction and check for
// overflow. This allows us to freely add any currency values in later
// validation functions without worrying about overflow.
Expand All @@ -529,38 +529,23 @@ func validateV2CurrencyValues(ms *MidState, txn types.V2Transaction) error {
add(ms.base.V2FileContractTax(fc))
}

for i, sco := range txn.SiacoinOutputs {
if sco.Value.IsZero() {
return fmt.Errorf("siacoin output %v has zero value", i)
}
for _, sco := range txn.SiacoinOutputs {
add(sco.Value)
}
for i, sfo := range txn.SiafundOutputs {
if sfo.Value == 0 {
return fmt.Errorf("siafund output %v has zero value", i)
}
for _, sfo := range txn.SiafundOutputs {
overflow = overflow || sfo.Value > ms.base.SiafundCount()
}
for i, fc := range txn.FileContracts {
if fc.RenterOutput.Value.IsZero() && fc.HostOutput.Value.IsZero() {
return fmt.Errorf("file contract %v has zero value", i)
}
for _, fc := range txn.FileContracts {
addContract(fc)
}
for _, fc := range txn.FileContractRevisions {
addContract(fc.Revision)
}
for i, fcr := range txn.FileContractResolutions {
switch r := fcr.Resolution.(type) {
case *types.V2FileContractRenewal:
if r.NewContract.RenterOutput.Value.IsZero() && r.NewContract.HostOutput.Value.IsZero() {
return fmt.Errorf("file contract renewal %v creates contract with zero value", i)
}
for _, fcr := range txn.FileContractResolutions {
if r, ok := fcr.Resolution.(*types.V2FileContractRenewal); ok {
addContract(r.NewContract)
add(r.RenterRollover)
add(r.HostRollover)
case *types.V2FileContractFinalization:
addContract(types.V2FileContract(*r))
}
}
add(txn.MinerFee)
Expand Down Expand Up @@ -608,7 +593,10 @@ func validateV2Siacoins(ms *MidState, txn types.V2Transaction) error {
for _, sci := range txn.SiacoinInputs {
inputSum = inputSum.Add(sci.Parent.SiacoinOutput.Value)
}
for _, out := range txn.SiacoinOutputs {
for i, out := range txn.SiacoinOutputs {
if out.Value.IsZero() {
return fmt.Errorf("siacoin output %v has zero value", i)
}
outputSum = outputSum.Add(out.Value)
}
for _, fc := range txn.FileContracts {
Expand Down Expand Up @@ -669,7 +657,10 @@ func validateV2Siafunds(ms *MidState, txn types.V2Transaction) error {
for _, in := range txn.SiafundInputs {
inputSum += in.Parent.SiafundOutput.Value
}
for _, out := range txn.SiafundOutputs {
for i, out := range txn.SiafundOutputs {
if out.Value == 0 {
return fmt.Errorf("siafund output %v has zero value", i)
}
outputSum += out.Value
}
if inputSum != outputSum {
Expand Down Expand Up @@ -728,6 +719,8 @@ func validateV2FileContracts(ms *MidState, txn types.V2Transaction) error {
return fmt.Errorf("has proof height (%v) that has already passed", fc.ProofHeight)
case fc.ExpirationHeight <= fc.ProofHeight:
return fmt.Errorf("leaves no time between proof height (%v) and expiration height (%v)", fc.ProofHeight, fc.ExpirationHeight)
case fc.RenterOutput.Value.IsZero() && fc.HostOutput.Value.IsZero():
return fmt.Errorf("has zero value")
case fc.MissedHostValue.Cmp(fc.HostOutput.Value) > 0:
return fmt.Errorf("has missed host value (%d H) exceeding valid host value (%d H)", fc.MissedHostValue, fc.HostOutput.Value)
case fc.TotalCollateral.Cmp(fc.HostOutput.Value) > 0:
Expand Down Expand Up @@ -819,11 +812,10 @@ func validateV2FileContracts(ms *MidState, txn types.V2Transaction) error {
return fmt.Errorf("file contract renewal %v has invalid host signature", i)
}
case *types.V2FileContractFinalization:
finalRevision := types.V2FileContract(*r)
if finalRevision.RevisionNumber != types.MaxRevisionNumber {
return fmt.Errorf("file contract finalization %v does not set maximum revision number", i)
} else if err := validateRevision(fcr.Parent, finalRevision, false); err != nil {
return fmt.Errorf("file contract finalization %v %s", i, err)
finalRevision := fcr.Parent.V2FileContract
finalRevision.RevisionNumber = types.MaxRevisionNumber
if !finalRevision.RenterPublicKey.VerifyHash(ms.base.ContractSigHash(finalRevision), types.Signature(*r)) {
return fmt.Errorf("file contract finalization %v has invalid signature", i)
}
case *types.V2StorageProof:
sp := *r
Expand Down Expand Up @@ -878,7 +870,7 @@ func validateFoundationUpdate(ms *MidState, txn types.V2Transaction) error {
func ValidateV2Transaction(ms *MidState, txn types.V2Transaction) error {
if ms.base.childHeight() < ms.base.Network.HardforkV2.AllowHeight {
return errors.New("v2 transactions are not allowed until v2 hardfork begins")
} else if err := validateV2CurrencyValues(ms, txn); err != nil {
} else if err := validateV2CurrencyOverflow(ms, txn); err != nil {
return err
} else if err := validateV2Siacoins(ms, txn); err != nil {
return err
Expand Down
22 changes: 3 additions & 19 deletions consensus/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,8 +850,7 @@ func TestValidateV2Block(t *testing.T) {
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)))
*r = types.V2FileContractFinalization(renterPrivateKey.SignHash(cs.ContractSigHash(txn.FileContractResolutions[i].Parent.V2FileContract)))
}
}
}
Expand Down Expand Up @@ -1447,25 +1446,10 @@ func TestValidateV2Block(t *testing.T) {
},
},
{
"file contract finalization that does not set maximum revision number",
"file contract finalization with wrong revision number",
func(b *types.Block) {
txn := &b.V2.Transactions[0]

resolution := types.V2FileContractFinalization(testFces[0].V2FileContract)
txn.FileContractResolutions = []types.V2FileContractResolution{{
Parent: testFces[0],
Resolution: &resolution,
}}
},
},
{
"file contract finalization with invalid revision",
func(b *types.Block) {
txn := &b.V2.Transactions[0]

resolution := types.V2FileContractFinalization(testFces[0].V2FileContract)
resolution.RevisionNumber = types.MaxRevisionNumber
resolution.TotalCollateral = types.ZeroCurrency
resolution := types.V2FileContractFinalization(renterPrivateKey.SignHash(cs.ContractSigHash((testFces[0].V2FileContract))))
txn.FileContractResolutions = []types.V2FileContractResolution{{
Parent: testFces[0],
Resolution: &resolution,
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module go.sia.tech/core

go 1.23.0
go 1.23.1

toolchain go1.23.2

require (
go.sia.tech/mux v1.3.0
golang.org/x/crypto v0.28.0
golang.org/x/sys v0.26.0
lukechampine.com/frand v1.4.2
lukechampine.com/frand v1.5.1
)

require github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
7 changes: 2 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
go.sia.tech/mux v1.3.0 h1:hgR34IEkqvfBKUJkAzGi31OADeW2y7D6Bmy/Jcbop9c=
go.sia.tech/mux v1.3.0/go.mod h1:I46++RD4beqA3cW9Xm9SwXbezwPqLvHhVs9HLpDtt58=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
lukechampine.com/frand v1.4.2 h1:RzFIpOvkMXuPMBb9maa4ND4wjBn71E1Jpf8BzJHMaVw=
lukechampine.com/frand v1.4.2/go.mod h1:4S/TM2ZgrKejMcKMbeLjISpJMO+/eZ1zu3vYX9dtj3s=
lukechampine.com/frand v1.5.1 h1:fg0eRtdmGFIxhP5zQJzM1lFDbD6CUfu/f+7WgAZd5/w=
lukechampine.com/frand v1.5.1/go.mod h1:4VstaWc2plN4Mjr10chUD46RAVGWhpkZ5Nja8+Azp0Q=
10 changes: 5 additions & 5 deletions types/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ func (ren V2FileContractRenewal) EncodeTo(e *Encoder) {

// EncodeTo implements types.EncoderTo.
func (fcf V2FileContractFinalization) EncodeTo(e *Encoder) {
V2FileContract(fcf).EncodeTo(e)
Signature(fcf).EncodeTo(e)
}

// EncodeTo implements types.EncoderTo.
Expand Down Expand Up @@ -840,9 +840,9 @@ func (txn V2TransactionSemantics) EncodeTo(e *Encoder) {
// normalize (being careful not to modify the original)
switch res := fcr.Resolution.(type) {
case *V2FileContractFinalization:
fc := *res
nilSigs(&fc.RenterSignature, &fc.HostSignature)
fcr.Resolution = &fc
fcf := *res
nilSigs((*Signature)(&fcf))
fcr.Resolution = &fcf
case *V2FileContractRenewal:
renewal := *res
nilSigs(
Expand Down Expand Up @@ -1291,7 +1291,7 @@ func (ren *V2FileContractRenewal) DecodeFrom(d *Decoder) {

// DecodeFrom implements types.DecoderFrom.
func (fcf *V2FileContractFinalization) DecodeFrom(d *Decoder) {
(*V2FileContract)(fcf).DecodeFrom(d)
(*Signature)(fcf).DecodeFrom(d)
}

// DecodeFrom implements types.DecoderFrom.
Expand Down
15 changes: 10 additions & 5 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,16 @@ func (txn *Transaction) FileContractID(i int) FileContractID {
return hashAll(SpecifierFileContract, (*txnSansSigs)(txn), i)
}

// TotalFees returns the sum of the transaction's miner fees.
// TotalFees returns the sum of the transaction's miner fees. If the sum would
// overflow, TotalFees returns ZeroCurrency.
func (txn *Transaction) TotalFees() Currency {
var sum Currency
var overflow bool
for _, fee := range txn.MinerFees {
sum = sum.Add(fee)
sum, overflow = sum.AddWithOverflow(fee)
if overflow {
return ZeroCurrency
}
}
return sum
}
Expand Down Expand Up @@ -502,8 +507,8 @@ type V2FileContractRevision struct {
// A V2FileContractResolution closes a v2 file contract's payment channel. There
// are four ways a contract can be resolved:
//
// 1) The renter and host can sign a final contract revision (a "finalization"),
// after which the contract cannot be revised further.
// 1) The renter can finalize the contract's current state, preventing further
// revisions and immediately creating its outputs.
//
// 2) The renter and host can jointly renew the contract. The old contract is
// finalized, and a portion of its funds are "rolled over" into a new contract.
Expand Down Expand Up @@ -547,7 +552,7 @@ func (*V2FileContractExpiration) isV2FileContractResolution() {}

// A V2FileContractFinalization finalizes a contract, preventing further
// revisions and immediately creating its valid outputs.
type V2FileContractFinalization V2FileContract
type V2FileContractFinalization Signature

// A V2FileContractRenewal renews a file contract.
type V2FileContractRenewal struct {
Expand Down

0 comments on commit efc26ef

Please sign in to comment.