Commit 6c6c8a34 authored by David Vorick's avatar David Vorick

safer types

parent 45884a18
......@@ -13,10 +13,10 @@ type SiaConstants struct {
BlockSizeLimit uint64
BlockFrequency types.BlockHeight
TargetWindow types.BlockHeight
MedianTimestampWindow int
MedianTimestampWindow uint64
FutureThreshold types.Timestamp
SiafundCount uint64
SiafundPortion float64
SiafundCount types.Currency
SiafundPortion *big.Rat
InitialCoinbase uint64
MinimumCoinbase uint64
......
......@@ -203,7 +203,7 @@ func (cs *State) applySiafundInputs(bn *blockNode, t types.Transaction) {
// Calculate the volume of siacoins to put in the claim output.
sfo := cs.siafundOutputs[sfi.ParentID]
claimPortion := cs.siafundPool.Sub(sfo.ClaimStart).Div(types.NewCurrency64(types.SiafundCount)).Mul(sfo.Value)
claimPortion := cs.siafundPool.Sub(sfo.ClaimStart).Div(types.SiafundCount).Mul(sfo.Value)
// Add the claim output to the delayed set of outputs.
sco := types.SiacoinOutput{
......
......@@ -58,7 +58,7 @@ func (bn *blockNode) earliestChildTimestamp() types.Timestamp {
// Get the previous MedianTimestampWindow timestamps.
windowTimes := make(types.TimestampSlice, types.MedianTimestampWindow)
current := bn
for i := 0; i < types.MedianTimestampWindow; i++ {
for i := uint64(0); i < types.MedianTimestampWindow; i++ {
windowTimes[i] = current.block.Timestamp
// If we are at the genesis block, keep using the genesis block for the
......
......@@ -95,7 +95,7 @@ func (cs *State) checkSiafunds() error {
for _, sfo := range cs.siafundOutputs {
totalSiafunds = totalSiafunds.Add(sfo.Value)
}
if totalSiafunds.Cmp(types.NewCurrency64(types.SiafundCount)) != 0 {
if totalSiafunds.Cmp(types.SiafundCount) != 0 {
return fmt.Errorf("checkSiafunds: expected %v siafunds, got %v siafunds", types.SiafundCount, totalSiafunds)
}
return nil
......
......@@ -40,7 +40,7 @@ func (w *Wallet) SiafundBalance() (siafundBalance types.Currency, siacoinClaimBa
csPool := w.state.SiafundPool()
for _, sfo := range w.siafundOutputs {
siafundBalance = siafundBalance.Add(sfo.Value)
siacoinsPerSiafund := csPool.Sub(sfo.ClaimStart).Div(types.NewCurrency64(types.SiafundCount))
siacoinsPerSiafund := csPool.Sub(sfo.ClaimStart).Div(types.SiafundCount)
siacoinClaim := siacoinsPerSiafund.Mul(sfo.Value)
siacoinClaimBalance = siacoinClaimBalance.Add(siacoinClaim)
}
......
......@@ -14,25 +14,25 @@ import (
)
var (
BlockSizeLimit uint64
BlockSizeLimit = uint64(2e6)
RootDepth = Target{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
BlockFrequency BlockHeight
MaturityDelay BlockHeight
GenesisTimestamp Timestamp
RootTarget Target
RootDepth Target
MedianTimestampWindow = uint64(11)
TargetWindow BlockHeight
MedianTimestampWindow int
MaxAdjustmentUp *big.Rat
MaxAdjustmentDown *big.Rat
FutureThreshold Timestamp
ExtremeFutureThreshold Timestamp
SiafundCount uint64
SiafundPortion float64
InitialCoinbase uint64
SiafundCount = NewCurrency64(10000)
SiafundPortion = big.NewRat(39, 1000)
SiacoinPrecision = NewCurrency(new(big.Int).Exp(big.NewInt(10), big.NewInt(24), nil))
InitialCoinbase = uint64(300e3)
MinimumCoinbase uint64
SiacoinPrecision Currency
GenesisSiafundAllocation []SiafundOutput
......@@ -42,20 +42,6 @@ var (
// init checks which build constant is in place and initializes the variables
// accordingly.
func init() {
// Constants that are consistent regardless of the build settings.
BlockSizeLimit = 2e6 // 1 MB
RootDepth = Target{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
MedianTimestampWindow = 11 // 11 Blocks.
SiafundCount = 10e3 // 10,000 total siafunds.
SiafundPortion = 0.039 // 3.9% fee on all file contract payouts.
InitialCoinbase = 300e3 // 300,000 Siacoins per block
SiacoinPrecision = NewCurrency( // Siacoin is divisible by 10^24
new(big.Int).Exp(big.NewInt(10), big.NewInt(24), nil),
)
// Constants that depend on build settings.
if build.Release == "dev" {
// 'dev' settings are for small developer testnets, usually on the same
// computer. Settings are slow enough that a small team of developers
......
......@@ -82,26 +82,22 @@ func (x Currency) Mul(y Currency) (c Currency) {
return
}
// MulFloat returns a new Currency value y = c * x, where x is a float64.
// Behavior is undefined when x is negative.
func (x Currency) MulFloat(y float64) (c Currency) {
if y < 0 {
// MulRat returns a new Currency value x = c * y, where y is a big.Rat.
func (x Currency) MulRat(y *big.Rat) (c Currency) {
if y.Sign() < 0 {
if build.DEBUG {
panic(ErrNegativeCurrency)
}
} else {
cRat := new(big.Rat).Mul(
new(big.Rat).SetInt(&x.i),
new(big.Rat).SetFloat64(y),
)
c.i.Div(cRat.Num(), cRat.Denom())
tmp := new(big.Rat).Mul(new(big.Rat).SetInt(&x.i), y)
c.i.Div(tmp.Num(), tmp.Denom())
}
return
}
// RoundDown returns the largest multiple of y <= x.
func (x Currency) RoundDown(y uint64) (c Currency) {
diff := new(big.Int).Mod(&x.i, new(big.Int).SetUint64(y))
func (x Currency) RoundDown(y Currency) (c Currency) {
diff := new(big.Int).Mod(&x.i, &y.i)
c.i.Sub(&x.i, diff)
return
}
......
......@@ -67,15 +67,15 @@ func TestCurrencyMul(t *testing.T) {
}
}
// TestCurrencyMulFloat probes the MulFloat function of the currency type.
func TestCurrencyMulFloat(t *testing.T) {
// TestCurrencyMulRat probes the MulRat function of the currency type.
func TestCurrencyMulRat(t *testing.T) {
c5 := NewCurrency64(5)
c7 := NewCurrency64(7)
c10 := NewCurrency64(10)
if c5.MulFloat(2).Cmp(c10) != 0 {
if c5.MulRat(big.NewRat(2, 1)).Cmp(c10) != 0 {
t.Error("Multiplying 5 by 2 should return 10")
}
if c5.MulFloat(1.5).Cmp(c7) != 0 {
if c5.MulRat(big.NewRat(3, 2)).Cmp(c7) != 0 {
t.Error("Multiplying 5 by 1.5 should return 7")
}
}
......@@ -85,7 +85,7 @@ func TestCurrencyRoundDown(t *testing.T) {
// 10,000 is chosen because that's how many siafunds there usually are.
c40000 := NewCurrency64(40000)
c45000 := NewCurrency64(45000)
if c45000.RoundDown(10000).Cmp(c40000) != 0 {
if c45000.RoundDown(NewCurrency64(10000)).Cmp(c40000) != 0 {
t.Error("rounding down 45000 to the nearest 10000 didn't work")
}
}
......@@ -215,9 +215,9 @@ func TestCurrencyEncoding(t *testing.T) {
}
}
// TestNegativeCurrencyMulFloat checks that negative numbers are rejected when
// calling MulFloat on the currency type.
func TestNegativeCurrencyMulFloat(t *testing.T) {
// TestNegativeCurrencyMulRat checks that negative numbers are rejected when
// calling MulRat on the currency type.
func TestNegativeCurrencyMulRat(t *testing.T) {
// In debug mode, attempting to get a negative currency results in a panic.
defer func() {
r := recover()
......@@ -227,7 +227,7 @@ func TestNegativeCurrencyMulFloat(t *testing.T) {
}()
c := NewCurrency64(12)
_ = c.MulFloat(-1)
_ = c.MulRat(big.NewRat(-1, 1))
}
// TestNegativeCurrencySub checks that negative numbers are prevented when
......
......@@ -122,5 +122,5 @@ func (fcid FileContractID) StorageProofOutputID(proofStatus ProofStatus, i int)
// Tax returns the amount of Currency that will be taxed from fc.
func (fc FileContract) Tax() Currency {
return fc.Payout.MulFloat(SiafundPortion).RoundDown(SiafundCount)
return fc.Payout.MulRat(SiafundPortion).RoundDown(SiafundCount)
}
......@@ -6,13 +6,6 @@ import (
// TestFileContractTax probes the Tax function.
func TestTax(t *testing.T) {
if SiafundPortion != 0.039 {
t.Error("SiafundPortion does not match expected value, Tax testing may be off")
}
if SiafundCount != 10000 {
t.Error("SiafundCount does not match expected value, Tax testing may be off")
}
fc := FileContract{
Payout: NewCurrency64(435000),
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment