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 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 (d *LastDirectoryBlockTransactions) ContainsTrans(txid interfaces.IHash) bool { for _, trans := range d.FactoidTransactions { if trans.TxID == txid.String() { return true } } return false }
func (d *LastDirectoryBlockTransactions) ContainsEntry(hash interfaces.IHash) bool { for _, entry := range d.Entries { if entry.Hash == hash.String() { return true } } return false }
// 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 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()) } }
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 }
func CreateReceipt(dbo interfaces.DBOverlay, entryID interfaces.IHash) (*Receipt, error) { receipt := new(Receipt) receipt.Entry = new(JSON) receipt.Entry.Key = entryID.String() //EBlock hash, err := dbo.FetchIncludedIn(entryID) if err != nil { return nil, err } if hash == nil { return nil, fmt.Errorf("Block containing entry not found") } eBlock, err := dbo.FetchEBlock(hash) if err != nil { return nil, err } if eBlock == nil { return nil, fmt.Errorf("EBlock not found") } hash = eBlock.DatabasePrimaryIndex() receipt.EntryBlockKeyMR = hash.(*primitives.Hash) entries := eBlock.GetEntryHashes() //fmt.Printf("eBlock entries - %v\n\n", entries) branch := primitives.BuildMerkleBranchForEntryHash(entries, entryID, true) blockNode := new(primitives.MerkleNode) left, err := eBlock.HeaderHash() if err != nil { return nil, err } blockNode.Left = left.(*primitives.Hash) blockNode.Right = eBlock.BodyKeyMR().(*primitives.Hash) blockNode.Top = hash.(*primitives.Hash) //fmt.Printf("eBlock blockNode - %v\n\n", blockNode) branch = append(branch, blockNode) receipt.MerkleBranch = append(receipt.MerkleBranch, branch...) //str, _ := eBlock.JSONString() //fmt.Printf("eBlock - %v\n\n", str) //DBlock hash, err = dbo.FetchIncludedIn(hash) if err != nil { return nil, err } if hash == nil { return nil, fmt.Errorf("Block containing EBlock not found") } dBlock, err := dbo.FetchDBlock(hash) if err != nil { return nil, err } if dBlock == nil { return nil, fmt.Errorf("DBlock not found") } //str, _ = dBlock.JSONString() //fmt.Printf("dBlock - %v\n\n", str) entries = dBlock.GetEntryHashesForBranch() //fmt.Printf("dBlock entries - %v\n\n", entries) //merkleTree := primitives.BuildMerkleTreeStore(entries) //fmt.Printf("dBlock merkleTree - %v\n\n", merkleTree) branch = primitives.BuildMerkleBranchForEntryHash(entries, receipt.EntryBlockKeyMR, true) blockNode = new(primitives.MerkleNode) left, err = dBlock.HeaderHash() if err != nil { return nil, err } blockNode.Left = left.(*primitives.Hash) blockNode.Right = dBlock.BodyKeyMR().(*primitives.Hash) blockNode.Top = hash.(*primitives.Hash) //fmt.Printf("dBlock blockNode - %v\n\n", blockNode) branch = append(branch, blockNode) receipt.MerkleBranch = append(receipt.MerkleBranch, branch...) //DirBlockInfo hash = dBlock.DatabasePrimaryIndex() receipt.DirectoryBlockKeyMR = hash.(*primitives.Hash) dirBlockInfo, err := dbo.FetchDirBlockInfoByKeyMR(hash) if err != nil { return nil, err } if dirBlockInfo != nil { dbi := dirBlockInfo.(*dbInfo.DirBlockInfo) receipt.BitcoinTransactionHash = dbi.BTCTxHash.(*primitives.Hash) receipt.BitcoinBlockHash = dbi.BTCBlockHash.(*primitives.Hash) } return receipt, nil }
// Called by AddServer Message func ProcessIdentityToAdminBlock(st *State, chainID interfaces.IHash, servertype int) bool { var matryoshkaHash interfaces.IHash var blockSigningKey [32]byte var btcKey [20]byte var btcKeyLevel byte var btcKeyType byte err := st.AddIdentityFromChainID(chainID) if err != nil { log.Println(err.Error()) return true } index := st.isIdentityChain(chainID) if index != -1 { id := st.Identities[index] zero := primitives.NewZeroHash() if id.SigningKey == nil || id.SigningKey.IsSameAs(zero) { log.Println("New Fed/Audit server [" + chainID.String()[:10] + "] does not have an Block Signing Key associated to it") if !statusIsFedOrAudit(id.Status) { st.removeIdentity(index) } return true } else { copy(blockSigningKey[:32], id.SigningKey.Bytes()[:32]) } if id.AnchorKeys == nil { log.Println("New Fed/Audit server [" + chainID.String()[:10] + "] does not have an BTC Anchor Key associated to it") if !statusIsFedOrAudit(id.Status) { st.removeIdentity(index) } return true } else { for _, aKey := range id.AnchorKeys { if strings.Compare(aKey.BlockChain, "BTC") == 0 { copy(btcKey[:20], aKey.SigningKey[:20]) } } } if id.MatryoshkaHash == nil || id.MatryoshkaHash.IsSameAs(zero) { log.Println("New Fed/Audit server [" + chainID.String()[:10] + "] does not have an Matryoshka Hash associated to it") if !statusIsFedOrAudit(id.Status) { st.removeIdentity(index) } return true } matryoshkaHash = id.MatryoshkaHash if servertype == 0 { id.Status = constants.IDENTITY_PENDING_FEDERATED_SERVER } else if servertype == 1 { id.Status = constants.IDENTITY_PENDING_AUDIT_SERVER } st.Identities[index] = id } else { log.Println("New Fed/Audit server [" + chainID.String()[:10] + "] does not have an identity associated to it") return true } // Add to admin block if servertype == 0 { st.LeaderPL.AdminBlock.AddFedServer(chainID) st.Identities[index].Status = constants.IDENTITY_PENDING_FEDERATED_SERVER } else if servertype == 1 { st.LeaderPL.AdminBlock.AddAuditServer(chainID) st.Identities[index].Status = constants.IDENTITY_PENDING_AUDIT_SERVER } st.LeaderPL.AdminBlock.AddFederatedServerSigningKey(chainID, &blockSigningKey) st.LeaderPL.AdminBlock.AddMatryoshkaHash(chainID, matryoshkaHash) st.LeaderPL.AdminBlock.AddFederatedServerBitcoinAnchorKey(chainID, btcKeyLevel, btcKeyType, &btcKey) return true }
func (st *State) AddIdentityFromChainID(cid interfaces.IHash) error { if cid.String() == st.GetNetworkBootStrapIdentity().String() { // Ignore Bootstrap Identity return nil } index := st.isIdentityChain(cid) if index == -1 { index = st.CreateBlankFactomIdentity(cid) } managementChain, _ := primitives.HexToHash(MAIN_FACTOM_IDENTITY_LIST) dbase := st.GetAndLockDB() ents, err := dbase.FetchAllEntriesByChainID(managementChain) st.UnlockDB() if err != nil { return err } if len(ents) == 0 { st.removeIdentity(index) return errors.New("Identity Error: No main Main Factom Identity Chain chain created") } // Check Identity chain eblkStackRoot := make([]interfaces.IEntryBlock, 0) mr, err := st.DB.FetchHeadIndexByChainID(cid) if err != nil { return err } else if mr == nil { st.removeIdentity(index) return errors.New("Identity Error: Identity Chain not found") } for !mr.IsSameAs(primitives.NewZeroHash()) { eblk, err := st.DB.FetchEBlock(mr) if err != nil || eblk == nil { break } eblkStackRoot = append(eblkStackRoot, eblk) mr = eblk.GetHeader().GetPrevKeyMR() } for i := len(eblkStackRoot) - 1; i >= 0; i-- { LoadIdentityByEntryBlock(eblkStackRoot[i], st) } mr, err = st.DB.FetchHeadIndexByChainID(managementChain) if err != nil { return err } // Check Factom Main Identity List for !mr.IsSameAs(primitives.NewZeroHash()) { eblk, err := st.DB.FetchEBlock(mr) if err != nil { return err } if eblk == nil { break } entries := eblk.GetEntryHashes() height := eblk.GetDatabaseHeight() for _, eHash := range entries { hs := eHash.String() if hs[0:10] != "0000000000" { //ignore minute markers ent, err := st.DB.FetchEntry(eHash) if err != nil || ent == nil { continue } if len(ent.ExternalIDs()) > 3 { // This is the Register Factom Identity Message if len(ent.ExternalIDs()[2]) == 32 { idChain := primitives.NewHash(ent.ExternalIDs()[2][:32]) if string(ent.ExternalIDs()[1]) == "Register Factom Identity" && cid.IsSameAs(idChain) { registerFactomIdentity(ent, cid, height, st) break // Found the registration } } } } } mr = eblk.GetHeader().GetPrevKeyMR() } eblkStackSub := make([]interfaces.IEntryBlock, 0) if st.Identities[index].ManagementChainID == nil { st.removeIdentity(index) return errors.New("Identity Error: No management chain found") } mr, err = st.DB.FetchHeadIndexByChainID(st.Identities[index].ManagementChainID) if err != nil { return err } else if mr == nil { st.removeIdentity(index) return nil } for !mr.IsSameAs(primitives.NewZeroHash()) { eblk, err := st.DB.FetchEBlock(mr) if err != nil { break } eblkStackSub = append(eblkStackSub, eblk) mr = eblk.GetHeader().GetPrevKeyMR() } for i := len(eblkStackSub) - 1; i >= 0; i-- { LoadIdentityByEntryBlock(eblkStackSub[i], st) } err = checkIdentityForFull(index, st) if err != nil { st.removeIdentity(index) return errors.New("Error: Identity not full - " + err.Error()) } return nil }