func (db *Overlay) FetchAllEntriesByChainID(chainID interfaces.IHash) ([]interfaces.IEBEntry, error) { list, err := db.FetchAllBlocksFromBucket(chainID.Bytes(), entryBlock.NewEntry()) if err != nil { return nil, err } return toEntryList(list), nil }
// End of Block means packing the current block away, and setting // up the next func (fs *FactoidState) ProcessEndOfBlock(state interfaces.IState) { var hash, hash2 interfaces.IHash if fs.GetCurrentBlock() == nil { panic("Invalid state on initialization") } hash = fs.CurrentBlock.GetHash() hash2 = fs.CurrentBlock.GetLedgerKeyMR() state.GetCurrentDirectoryBlock().GetDBEntries()[2].SetKeyMR(hash) if err := state.GetDB().SaveFactoidBlockHead(fs.CurrentBlock); err != nil { panic(err) } state.SetPrevFactoidKeyMR(hash) fs.CurrentBlock = block.NewFBlock(fs.GetFactoshisPerEC(), state.GetDBHeight()+1) t := coinbase.GetCoinbase(primitives.GetTimeMilli()) err := fs.CurrentBlock.AddCoinbase(t) if err != nil { panic(err.Error()) } fs.UpdateTransaction(t) if hash != nil { fs.CurrentBlock.SetPrevKeyMR(hash.Bytes()) fs.CurrentBlock.SetPrevLedgerKeyMR(hash2.Bytes()) } }
func addServerSigningKey(chainID interfaces.IHash, key interfaces.IHash, height uint32, st *State) { AuthorityIndex := st.AddAuthorityFromChainID(chainID) if st.IdentityChainID.IsSameAs(chainID) && len(st.serverPendingPrivKeys) > 0 { for i, pubKey := range st.serverPendingPubKeys { pubData, err := pubKey.MarshalBinary() if err != nil { break } if bytes.Compare(pubData, key.Bytes()) == 0 { st.serverPrivKey = st.serverPendingPrivKeys[i] st.serverPubKey = st.serverPendingPubKeys[i] if len(st.serverPendingPrivKeys) > i+1 { st.serverPendingPrivKeys = append(st.serverPendingPrivKeys[:i], st.serverPendingPrivKeys[i+1:]...) st.serverPendingPubKeys = append(st.serverPendingPubKeys[:i], st.serverPendingPubKeys[i+1:]...) } else { st.serverPendingPrivKeys = st.serverPendingPrivKeys[:i] st.serverPendingPubKeys = st.serverPendingPubKeys[:i] } break } } } // Add Key History st.Authorities[AuthorityIndex].KeyHistory = append(st.Authorities[AuthorityIndex].KeyHistory, struct { ActiveDBHeight uint32 SigningKey primitives.PublicKey }{height, st.Authorities[AuthorityIndex].SigningKey}) // Replace Active Key st.Authorities[AuthorityIndex].SigningKey = primitives.PubKeyFromString(key.String()) }
// HashMerkleBranches takes two hashes, treated as the left and right tree // nodes, and returns the hash of their concatenation. This is a helper // function used to aid in the generation of a merkle tree. func HashMerkleBranches(left interfaces.IHash, right interfaces.IHash) interfaces.IHash { // Concatenate the left and right nodes. var barray []byte = make([]byte, constants.ADDRESS_LENGTH*2) copy(barray[:constants.ADDRESS_LENGTH], left.Bytes()) copy(barray[constants.ADDRESS_LENGTH:], right.Bytes()) newSha := Sha(barray) return newSha }
func (db *Overlay) FetchPrimaryIndexBySecondaryIndex(secondaryIndexBucket []byte, key interfaces.IHash) (interfaces.IHash, error) { block, err := db.DB.Get(secondaryIndexBucket, key.Bytes(), new(primitives.Hash)) if err != nil { return nil, err } if block == nil { return nil, nil } return block.(interfaces.IHash), nil }
func (db *Overlay) FetchBlock(bucket []byte, key interfaces.IHash, dst interfaces.DatabaseBatchable) (interfaces.DatabaseBatchable, error) { block, err := db.DB.Get(bucket, key.Bytes(), dst) if err != nil { return nil, err } if block == nil { return nil, nil } return block.(interfaces.DatabaseBatchable), nil }
func (db *Overlay) FetchPaidFor(hash interfaces.IHash) (interfaces.IHash, error) { block, err := db.DB.Get(PAID_FOR, hash.Bytes(), new(primitives.Hash)) if err != nil { return nil, err } if block == nil { return nil, nil } return block.(interfaces.IHash), nil }
func (db *Overlay) FetchIncludedIn(hash interfaces.IHash) (interfaces.IHash, error) { block, err := db.DB.Get(INCLUDED_IN, hash.Bytes(), new(primitives.Hash)) if err != nil { return nil, err } if block == nil { return nil, nil } return block.(interfaces.IHash), nil }
// Compare two Hashes func (a Hash) IsSameAs(b interfaces.IHash) bool { if b == nil { return false } if bytes.Compare(a[:], b.Bytes()) == 0 { return true } return false }
func (db *Overlay) SavePaidFor(entry, ecEntry interfaces.IHash) error { if entry == nil || ecEntry == nil { return nil } batch := []interfaces.Record{} batch = append(batch, interfaces.Record{PAID_FOR, entry.Bytes(), ecEntry}) err := db.DB.PutInBatch(batch) if err != nil { return err } return nil }
func (db *Overlay) SaveIncludedIn(entry, block interfaces.IHash) error { if entry == nil || block == nil { return nil } batch := []interfaces.Record{} batch = append(batch, interfaces.Record{INCLUDED_IN, entry.Bytes(), block}) err := db.DB.PutInBatch(batch) if err != nil { return err } return nil }
// Returns true and the index of this server, or false and the insertion point for this server func (p *ProcessList) GetAuditServerIndexHash(identityChainID interfaces.IHash) (bool, int) { if p == nil { return false, 0 } p.SortAuditServers() scid := identityChainID.Bytes() for i, fs := range p.AuditServers { // Find and remove if bytes.Compare(scid, fs.GetChainID().Bytes()) == 0 { return true, i } } return false, len(p.AuditServers) }
// FetchHeadMRByChainID gets an index of the highest block from the database. func (db *Overlay) FetchHeadIndexByChainID(chainID interfaces.IHash) (interfaces.IHash, error) { if chainID == nil { return nil, nil } bucket := []byte{byte(CHAIN_HEAD)} key := chainID.Bytes() block, err := db.DB.Get(bucket, key, new(primitives.Hash)) if err != nil { return nil, err } if block == nil { return nil, nil } return block.(interfaces.IHash), nil }
// FetchAllEBlocksByChain gets all of the blocks by chain id func (db *Overlay) FetchAllEBlocksByChain(chainID interfaces.IHash) ([]interfaces.IEntryBlock, error) { bucket := append([]byte{byte(ENTRYBLOCK_CHAIN_NUMBER)}, chainID.Bytes()...) keyList, err := db.FetchAllBlocksFromBucket(bucket, new(primitives.Hash)) if err != nil { return nil, err } list := make([]interfaces.IEntryBlock, len(keyList)) for i, v := range keyList { block, err := db.FetchEBlockByKeyMR(v.(interfaces.IHash)) if err != nil { return nil, err } list[i] = block } return list, nil }
func (db *Overlay) SavePaidForMultiFromBlock(block interfaces.IEntryCreditBlock, checkForDuplicateEntries bool) error { if block == nil { return nil } batch := []interfaces.Record{} for _, entry := range block.GetBody().GetEntries() { if entry.ECID() != entryCreditBlock.ECIDChainCommit && entry.ECID() != entryCreditBlock.ECIDEntryCommit { continue } var entryHash interfaces.IHash if entry.ECID() == entryCreditBlock.ECIDChainCommit { entryHash = entry.(*entryCreditBlock.CommitChain).EntryHash } if entry.ECID() == entryCreditBlock.ECIDEntryCommit { entryHash = entry.(*entryCreditBlock.CommitEntry).EntryHash } if checkForDuplicateEntries == true { loaded, err := db.Get(PAID_FOR, entryHash.Bytes(), primitives.NewZeroHash()) if err != nil { return err } if loaded != nil { continue } } batch = append(batch, interfaces.Record{PAID_FOR, entryHash.Bytes(), entry.Hash()}) } if len(batch) == 0 { return nil } err := db.DB.PutInBatch(batch) if err != nil { return err } return nil }
func (a *Anchor) doTransaction(hash interfaces.IHash, blockHeight uint32, dirBlockInfo *dbInfo.DirBlockInfo) (*wire.ShaHash, error) { b := a.balances[0] a.balances = a.balances[1:] anchorLog.Info("new balances.len=", len(a.balances)) msgtx, err := a.createRawTransaction(b, hash.Bytes(), blockHeight) if err != nil { return nil, fmt.Errorf("cannot create Raw Transaction: %s", err) } shaHash, err := a.sendRawTransaction(msgtx) if err != nil { return nil, fmt.Errorf("cannot send Raw Transaction: %s", err) } if dirBlockInfo != nil { dirBlockInfo.BTCTxHash = toHash(shaHash) dirBlockInfo.SetTimestamp(primitives.NewTimestampNow()) a.db.SaveDirBlockInfo(dirBlockInfo) } return shaHash, nil }
// Create a new DB Signature Entry func NewAddFederatedServer(identityChainID interfaces.IHash, dbheight uint32) (e *AddFederatedServer) { e = new(AddFederatedServer) e.DBHeight = dbheight e.IdentityChainID = primitives.NewHash(identityChainID.Bytes()) return }
func toShaHash(hash interfaces.IHash) *wire.ShaHash { h, _ := wire.NewShaHash(hash.Bytes()) return h }
func (m *MessageBase) SetFullMsgHash(hash interfaces.IHash) { m.GetFullMsgHash().SetBytes(hash.Bytes()) }
func CreateAddress(hash interfaces.IHash) interfaces.IAddress { return NewAddress(hash.Bytes()) }
func (db *Overlay) FetchAllEntryIDsByChainID(chainID interfaces.IHash) ([]interfaces.IHash, error) { return db.FetchAllBlockKeysFromBucket(chainID.Bytes()) }
// Process messages and update our state. func (p *ProcessList) Process(state *State) (progress bool) { dbht := state.GetHighestCompletedBlock() if dbht >= p.DBHeight { return true } state.PLProcessHeight = p.DBHeight p.AskDBState(0, p.VMs[0].Height) // Look for a possible dbstate at this height. if len(p.System.List) > 0 { systemloop: for i, f := range p.System.List[p.System.Height:] { fault, ok := f.(*messages.FullServerFault) if ok { vm := p.VMs[fault.VMIndex] if vm.Height < int(fault.Height) { break systemloop } if !fault.Process(p.DBHeight, p.State) { return false } p.System.Height++ progress = true } if fault == nil { p.Ask(-1, i, 10, 100) } } } for i := 0; i < len(p.FedServers); i++ { vm := p.VMs[i] if !p.State.Syncing { vm.whenFaulted = 0 p.Unfault() } else { if !vm.Synced { eomFault(p, vm, i, len(vm.List), 0) } } if vm.Height == len(vm.List) && p.State.Syncing && !vm.Synced { // means that we are missing an EOM p.Ask(i, vm.Height, 0, 1) } // If we haven't heard anything from a VM, ask for a message at the last-known height if vm.Height == len(vm.List) { p.Ask(i, vm.Height, 20, 2) } if vm.whenFaulted > 0 && vm.Height > vm.faultHeight { if p.AmINegotiator && i == p.NegotiatorVMIndex { p.AmINegotiator = false } vm.faultHeight = -1 vm.whenFaulted = 0 p.Unfault() } VMListLoop: for j := vm.Height; j < len(vm.List); j++ { if vm.List[j] == nil { p.Ask(i, j, 0, 3) break VMListLoop } thisAck := vm.ListAck[j] var expectedSerialHash interfaces.IHash var err error if vm.Height == 0 { expectedSerialHash = thisAck.SerialHash } else { last := vm.ListAck[vm.Height-1] expectedSerialHash, err = primitives.CreateHash(last.MessageHash, thisAck.MessageHash) if err != nil { p.Ask(i, j, 3, 4) break VMListLoop } // compare the SerialHash of this acknowledgement with the // expected serialHash (generated above) if !expectedSerialHash.IsSameAs(thisAck.SerialHash) { fmt.Printf("dddd %20s %10s --- %10s %10x %10s %10x \n", "Conflict", p.State.FactomNodeName, "expected", expectedSerialHash.Bytes()[:3], "This", thisAck.Bytes()[:3]) fmt.Printf("dddd Error detected on %s\nSerial Hash failure: Fed Server %d Leader ID %x List Ht: %d \nDetected on: %s\n", state.GetFactomNodeName(), i, p.FedServers[i].GetChainID().Bytes()[:3], j, vm.List[j].String()) fmt.Printf("dddd Last Ack: %6x Last Serial: %6x\n", last.GetHash().Bytes()[:3], last.SerialHash.Bytes()[:3]) fmt.Printf("dddd This Ack: %6x This Serial: %6x\n", thisAck.GetHash().Bytes()[:3], thisAck.SerialHash.Bytes()[:3]) fmt.Printf("dddd Expected: %6x\n", expectedSerialHash.Bytes()[:3]) fmt.Printf("dddd The message that didn't work: %s\n\n", vm.List[j].String()) // the SerialHash of this acknowledgment is incorrect // according to this node's processList //fault(p, i, 0, vm, 0, j, 2) p.State.Reset() return } } // So here is the deal. After we have processed a block, we have to allow the DirectoryBlockSignatures a chance to save // to disk. Then we can insist on having the entry blocks. diff := p.DBHeight - state.EntryBlockDBHeightComplete _, dbsig := vm.List[j].(*messages.DirectoryBlockSignature) // Keep in mind, the process list is processing at a height one greater than the database. 1 is caught up. 2 is one behind. // Until the signatures are processed, we will be 2 behind. if (dbsig && diff <= 2) || diff <= 1 { // If we can't process this entry (i.e. returns false) then we can't process any more. p.NextHeightToProcess[i] = j + 1 if vm.List[j].Process(p.DBHeight, state) { // Try and Process this entry vm.heartBeat = 0 vm.Height = j + 1 // Don't process it again if the process worked. //p.Unfault() progress = true } else { break VMListLoop // Don't process further in this list, go to the next. } } else { // If we don't have the Entry Blocks (or we haven't processed the signatures) we can't do more. break VMListLoop } } } return }