// newTestingFile initializes a file object with random parameters. func newTestingFile() *file { key, _ := crypto.GenerateTwofishKey() data, _ := crypto.RandBytes(8) nData, _ := crypto.RandIntn(10) nParity, _ := crypto.RandIntn(10) rsc, _ := NewRSCode(nData+1, nParity+1) return &file{ name: "testfile-" + strconv.Itoa(int(data[0])), size: encoding.DecUint64(data[1:5]), masterKey: key, erasureCode: rsc, pieceSize: encoding.DecUint64(data[6:8]), } }
// minimumValidChildTimestamp returns the earliest timestamp that a child node // can have while still being valid. See section 'Block Timestamps' in // Consensus.md. // // To boost performance, minimumValidChildTimestamp is passed a bucket that it // can use from inside of a boltdb transaction. func (rh stdBlockRuleHelper) minimumValidChildTimestamp(blockMap dbBucket, pb *processedBlock) types.Timestamp { // Get the previous MedianTimestampWindow timestamps. windowTimes := make(types.TimestampSlice, types.MedianTimestampWindow) windowTimes[0] = pb.Block.Timestamp parent := pb.Block.ParentID for i := uint64(1); i < types.MedianTimestampWindow; i++ { // If the genesis block is 'parent', use the genesis block timestamp // for all remaining times. if parent == (types.BlockID{}) { windowTimes[i] = windowTimes[i-1] continue } // Get the next parent's bytes. Because the ordering is specific, the // parent does not need to be decoded entirely to get the desired // information. This provides a performance boost. The id of the next // parent lies at the first 32 bytes, and the timestamp of the block // lies at bytes 40-48. parentBytes := blockMap.Get(parent[:]) copy(parent[:], parentBytes[:32]) windowTimes[i] = types.Timestamp(encoding.DecUint64(parentBytes[40:48])) } sort.Sort(windowTimes) // Return the median of the sorted timestamps. return windowTimes[len(windowTimes)/2] }
// targetAdjustmentBase returns the magnitude that the target should be // adjusted by before a clamp is applied. func (cs *ConsensusSet) targetAdjustmentBase(blockMap *bolt.Bucket, pb *processedBlock) *big.Rat { // Grab the block that was generated 'TargetWindow' blocks prior to the // parent. If there are not 'TargetWindow' blocks yet, stop at the genesis // block. var windowSize types.BlockHeight parent := pb.Block.ParentID current := pb.Block.ID() for windowSize = 0; windowSize < types.TargetWindow && parent != (types.BlockID{}); windowSize++ { current = parent copy(parent[:], blockMap.Get(parent[:])[:32]) } timestamp := types.Timestamp(encoding.DecUint64(blockMap.Get(current[:])[40:48])) // The target of a child is determined by the amount of time that has // passed between the generation of its immediate parent and its // TargetWindow'th parent. The expected amount of seconds to have passed is // TargetWindow*BlockFrequency. The target is adjusted in proportion to how // time has passed vs. the expected amount of time to have passed. // // The target is converted to a big.Rat to provide infinite precision // during the calculation. The big.Rat is just the int representation of a // target. timePassed := pb.Block.Timestamp - timestamp expectedTimePassed := types.BlockFrequency * windowSize return big.NewRat(int64(timePassed), int64(expectedTimePassed)) }
// UnmarshalSia implements the encoding.SiaUnmarshaler interface. func (b *Block) UnmarshalSia(r io.Reader) error { io.ReadFull(r, b.ParentID[:]) io.ReadFull(r, b.Nonce[:]) tsBytes := make([]byte, 8) io.ReadFull(r, tsBytes) b.Timestamp = Timestamp(encoding.DecUint64(tsBytes)) return encoding.NewDecoder(r).DecodeAll(&b.MinerPayouts, &b.Transactions) }
// stopConsistencyGuard is the complement function to startConsistencyGuard. // startConsistencyGuard should be called any time that consensus changes are // starting, and stopConsistencyGuard should be called when the consensus // changes are finished. The guards are necessary because one set of changes // may occur over multiple boltdb transactions. func (db *setDB) stopConsistencyGuard() { err := db.Update(func(tx *bolt.Tx) error { cg := tx.Bucket(ConsistencyGuard) i := encoding.DecUint64(cg.Get(GuardEnd)) return cg.Put(GuardEnd, encoding.EncUint64(i+1)) }) if err != nil && build.DEBUG { panic(err) } }
// startConsistencyGuard activates a consistency guard on the database. This is // necessary because the consensus set makes one atomic database change, but // does so using several boltdb transactions. The 'guard' is actually two // values, a 'GuardStart' and a 'GuardEnd'. 'GuardStart' is incremented when // consensus changes begin, and 'GuardEnd' is incremented when consensus // changes finish. If 'GuardStart' is not equal to 'GuardEnd' when // startConsistencyGuard is called, the database is likely corrupt. func (db *setDB) startConsistencyGuard() error { return db.Update(func(tx *bolt.Tx) error { cg := tx.Bucket(ConsistencyGuard) gs := cg.Get(GuardStart) if !bytes.Equal(gs, cg.Get(GuardEnd)) { return errDBInconsistent } i := encoding.DecUint64(gs) return cg.Put(GuardStart, encoding.EncUint64(i+1)) }) }
// startConsistencyGuard activates a consistency guard on the database. This is // necessary because the consensus set makes one atomic database change, but // does so using several boltdb transactions. The 'guard' is actually two // values, a 'GuardStart' and a 'GuardEnd'. 'GuardStart' is incremented when // consensus changes begin, and 'GuardEnd' is incremented when consensus // changes finish. If 'GuardStart' is not equal to 'GuardEnd' when // startConsistencyGuard is called, the database is likely corrupt. func (db *setDB) startConsistencyGuard() error { return db.Update(func(tx *bolt.Tx) error { cg := tx.Bucket(ConsistencyGuard) gs := cg.Get(GuardStart) if !bytes.Equal(gs, cg.Get(GuardEnd)) { println("Database is inconsistent - please reset your database by redownloading it or loading a consistent backup. This can happen if you close Sia unexpectedly.") return errDBInconsistent } i := encoding.DecUint64(gs) return cg.Put(GuardStart, encoding.EncUint64(i+1)) }) }