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()) }
func registerFactomIdentity(entry interfaces.IEBEntry, chainID interfaces.IHash, height uint32, st *State) error { extIDs := entry.ExternalIDs() if len(extIDs) == 0 { return errors.New("Identity Error Register Identity: Invalid external ID length") } if bytes.Compare([]byte{0x00}, extIDs[0]) != 0 || // Version !CheckExternalIDsLength(extIDs, []int{1, 24, 32, 33, 64}) { // Signiture return errors.New("Identity Error Register Identity: Invalid external ID length") } // find the Identity index from the chain id in the external id. add this chainID as the management id idChain := primitives.NewHash(extIDs[2]) IdentityIndex := st.isIdentityChain(idChain) if IdentityIndex == -1 { IdentityIndex = st.CreateBlankFactomIdentity(idChain) } sigmsg, err := AppendExtIDs(extIDs, 0, 2) if err != nil { return err } else { // Verify Signature idKey := st.Identities[IdentityIndex].Key1 if CheckSig(idKey, extIDs[3][1:33], sigmsg, extIDs[4]) { st.Identities[IdentityIndex].ManagementRegistered = height } else { return errors.New("New Management Chain Register for identity [" + chainID.String()[:10] + "] is invalid. Bad signiture") } } st.Identities[IdentityIndex].IdentityRegistered = height return nil }
func (s *State) FetchPaidFor(hash interfaces.IHash) (interfaces.IHash, error) { //TODO: expand to search data from outside database if hash == nil { return nil, nil } ecBlock := s.ProcessLists.LastList().EntryCreditBlock for _, tx := range ecBlock.GetEntries() { switch tx.ECID() { case entryCreditBlock.ECIDEntryCommit: if hash.IsSameAs(tx.(*entryCreditBlock.CommitEntry).EntryHash) { return tx.GetSigHash(), nil } break case entryCreditBlock.ECIDChainCommit: if hash.IsSameAs(tx.(*entryCreditBlock.CommitChain).EntryHash) { return tx.GetSigHash(), nil } break } } dbase := s.GetAndLockDB() defer s.UnlockDB() return dbase.FetchPaidFor(hash) }
// Validate the message, given the state. Three possible results: // < 0 -- Message is invalid. Discard // 0 -- Cannot tell if message is Valid // 1 -- Message is valid func (m *DataResponse) Validate(state interfaces.IState) int { var dataHash interfaces.IHash var err error switch m.DataType { case 0: // DataType = entry dataObject, ok := m.DataObject.(interfaces.IEBEntry) if !ok { return -1 } dataHash = dataObject.GetHash() case 1: // DataType = eblock dataObject, ok := m.DataObject.(interfaces.IEntryBlock) if !ok { return -1 } dataHash, err = dataObject.KeyMR() if err != nil { return -1 } default: // DataType currently not supported, treat as invalid return -1 } if dataHash.IsSameAs(m.DataHash) { return 1 } return -1 }
func (s *State) PutCommit(hash interfaces.IHash, msg interfaces.IMsg) { cs := s.Commits[hash.Fixed()] if cs == nil { cs = make([]interfaces.IMsg, 0) } s.Commits[hash.Fixed()] = append(cs, msg) }
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 }
// Gets the authority matching the identity ChainID. // Returns the authority and the int of its type: // 1 -> Federated // 0 -> Audit // -1 -> Not fed or audit // -2 -> Not found func (st *State) GetAuthority(serverID interfaces.IHash) (*Authority, int) { for _, auth := range st.Authorities { if serverID.IsSameAs(auth.AuthorityChainID) { return auth, auth.Type() } } return nil, -2 }
// SendRawTransactionToBTC is the main function used to anchor factom // dir block hash to bitcoin blockchain func (a *Anchor) SendRawTransactionToBTC(hash interfaces.IHash, blockHeight uint32) (*wire.ShaHash, error) { anchorLog.Debug("SendRawTransactionToBTC: hash=", hash.String(), ", dir block height=", blockHeight) //strconv.FormatUint(blockHeight, 10)) dirBlockInfo, err := a.sanityCheck(hash) if err != nil { return nil, err } return a.doTransaction(hash, blockHeight, dirBlockInfo) }
func (d *LastDirectoryBlockTransactions) ContainsEntry(hash interfaces.IHash) bool { for _, entry := range d.Entries { if entry.Hash == hash.String() { return true } } return false }
func (d *LastDirectoryBlockTransactions) ContainsTrans(txid interfaces.IHash) bool { for _, trans := range d.FactoidTransactions { if trans.TxID == txid.String() { return true } } return false }
// 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 }
// Create a sha hash from the message binary (output of BtcEncode) func (msg *MsgRevealChain) Sha() (interfaces.IHash, error) { buf := bytes.NewBuffer(nil) msg.BtcEncode(buf, ProtocolVersion) var sha interfaces.IHash _ = sha.SetBytes(Sha256(buf.Bytes())) return sha, nil }
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 }
func (c *ECBlock) GetEntryByHash(hash interfaces.IHash) interfaces.IECBlockEntry { if hash == nil { return nil } txs := c.GetEntries() for _, tx := range txs { if hash.IsSameAs(tx.Hash()) { return tx } if hash.IsSameAs(tx.GetSigHash()) { return tx } } return nil }
func (c *FBlock) GetTransactionByHash(hash interfaces.IHash) interfaces.ITransaction { if hash == nil { return nil } txs := c.GetTransactions() for _, tx := range txs { if hash.IsSameAs(tx.GetHash()) { return tx } if hash.IsSameAs(tx.GetSigHash()) { return tx } } return nil }
func TestChain(t *testing.T) { head, err := GetDBlockHead() if err != nil { t.Errorf("%v", err) } dHead, err := GetDBlock(head) if err != nil { t.Errorf("%v", err) } var h interfaces.IHash for _, e := range dHead.GetDBEntries() { if e.GetChainID().String() == "000000000000000000000000000000000000000000000000000000000000000a" { h = e.GetKeyMR() break } } for { if h.String() == "0000000000000000000000000000000000000000000000000000000000000000" { break } aBlock, err := GetABlock(h.String()) if err != nil { t.Errorf("Error fetching %v - %v", h.String(), err) t.FailNow() } h = aBlock.GetHeader().GetPrevBackRefHash() t.Logf("Fetched ABlock #%v", aBlock.GetDBHeight()) } }
// 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 }
// Returns the oldest, not processed, Commit received func (s *State) NextCommit(hash interfaces.IHash) interfaces.IMsg { cs := s.Commits[hash.Fixed()] if cs == nil { return nil } if len(cs) == 0 { delete(s.Commits, hash.Fixed()) return nil } r := cs[0] copy(cs[:], cs[1:]) cs[len(cs)-1] = nil s.Commits[hash.Fixed()] = cs[:len(cs)-1] return r }
// 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 (s *State) FetchEntryByHash(hash interfaces.IHash) (interfaces.IEBEntry, error) { //TODO: expand to search data from outside database if hash == nil { return nil, nil } pl := s.ProcessLists.LastList() keys := pl.GetKeysNewEntries() for _, key := range keys { tx := pl.GetNewEntry(key) if hash.IsSameAs(tx.GetHash()) { return tx, nil } } dbase := s.GetAndLockDB() defer s.UnlockDB() return dbase.FetchEntry(hash) }
// 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 (a *Anchor) sanityCheck(hash interfaces.IHash) (*dbInfo.DirBlockInfo, error) { index := sort.Search(len(a.dirBlockInfoSlice), func(i int) bool { return a.dirBlockInfoSlice[i].GetDBMerkleRoot().IsSameAs(hash) }) var dirBlockInfo *dbInfo.DirBlockInfo ok := false if index < len(a.dirBlockInfoSlice) { dirBlockInfo, ok = a.dirBlockInfoSlice[index].(*dbInfo.DirBlockInfo) } if dirBlockInfo == nil || !ok { s := fmt.Sprintf("Anchor Error: hash %s does not exist in dirBlockInfoSlice.\n", hash.String()) anchorLog.Error(s) return nil, errors.New(s) } if dirBlockInfo.BTCConfirmed { s := fmt.Sprintf("Anchor Warning: hash %s has already been confirmed in btc block chain.\n", hash.String()) anchorLog.Error(s) return nil, errors.New(s) } if a.dclient == nil || a.wclient == nil { s := fmt.Sprintf("\n\n$$$ WARNING: rpc clients and/or wallet are not initiated successfully. No anchoring for now.\n") anchorLog.Warning(s) return nil, errors.New(s) } if len(a.balances) == 0 { anchorLog.Warning("len(balances) == 0, start rescan UTXO *** ") a.updateUTXO(a.minBalance) } if len(a.balances) == 0 { anchorLog.Warning("len(balances) == 0, start rescan UTXO *** ") a.updateUTXO(a.fee) } if len(a.balances) == 0 { s := fmt.Sprintf("\n\n$$$ WARNING: No balance in your wallet. No anchoring for now.\n") anchorLog.Warning(s) return nil, errors.New(s) } return dirBlockInfo, nil }