Example #1
0
func (this *State) ExchangeRateAuthorityIsValid(e interfaces.IEBEntry) bool {

	// convert the conf quthority address into a
	authorityAddress := base58.Decode(this.ExchangeRateAuthorityAddress)
	ecPubPrefix := []byte{0x59, 0x2a}

	if !bytes.Equal(authorityAddress[:2], ecPubPrefix) {
		fmt.Errorf("Invalid Entry Credit Private Address")
		return false
	}

	pub := new([32]byte)
	copy(pub[:], authorityAddress[2:34])

	// in case verify can't handle empty public key
	if this.ExchangeRateAuthorityAddress == "" {
		return false
	}
	sig := new([64]byte)
	externalIds := e.ExternalIDs()

	// check for number of ext ids
	if len(externalIds) < 1 {
		return false
	}

	copy(sig[:], externalIds[0]) // First ext id needs to be the signature of the content

	if !ed.VerifyCanonical(pub, e.GetContent(), sig) {
		return false
	}

	return true
}
Example #2
0
func registerIdentityAsServer(entry interfaces.IEBEntry, 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, 26, 32, 33, 64}) { // Signiture
		return errors.New("Identity Error Register Identity: Invalid external ID length")
	}
	chainID := entry.GetChainID()
	IdentityIndex := st.isIdentityChain(chainID)
	if IdentityIndex == -1 {
		IdentityIndex = st.CreateBlankFactomIdentity(chainID)
	}

	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
			st.Identities[IdentityIndex].ManagementChainID = primitives.NewHash(extIDs[2][:32])
		} else {
			return errors.New("New Management Chain Register for identity [" + chainID.String()[:10] + "] is invalid. Bad signiture")
		}

	}
	return nil
}
Example #3
0
// AddEBEntry creates a new Entry Block Entry from the provided Factom Entry
// and adds it to the Entry Block Body.
func (e *EBlock) AddEBEntry(entry interfaces.IEBEntry) error {
	e.Body.EBEntries = append(e.Body.EBEntries, entry.GetHash())
	if err := e.BuildHeader(); err != nil {
		return err
	}
	return nil
}
Example #4
0
func addIdentity(entry interfaces.IEBEntry, height uint32, st *State) error {
	extIDs := entry.ExternalIDs()
	// This check is here to prevent possible index out of bounds with extIDs[:6]
	if len(extIDs) != 7 {
		return errors.New("Identity Error Create Management: Invalid external ID length")
	}
	if bytes.Compare([]byte{0x00}, extIDs[0]) != 0 || // Version
		!CheckExternalIDsLength(extIDs[:6], []int{1, 14, 32, 32, 32, 32}) { // Nonce
		return errors.New("Identity Error Create Identity Chain: Invalid external ID length")
	}

	chainID := entry.GetChainID()

	IdentityIndex := st.isIdentityChain(chainID)

	if IdentityIndex == -1 {
		IdentityIndex = st.CreateBlankFactomIdentity(chainID)
	}
	h := primitives.NewHash(extIDs[2])
	st.Identities[IdentityIndex].Key1 = h
	h = primitives.NewHash(extIDs[3])
	st.Identities[IdentityIndex].Key2 = h
	h = primitives.NewHash(extIDs[4])
	st.Identities[IdentityIndex].Key3 = h
	h = primitives.NewHash(extIDs[5])
	st.Identities[IdentityIndex].Key4 = h
	st.Identities[IdentityIndex].IdentityCreated = height
	return nil
}
Example #5
0
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
}
Example #6
0
// NewChainID generates a ChainID from an entry. ChainID = primitives.Sha(Sha(ExtIDs[0]) +
// Sha(ExtIDs[1] + ... + Sha(ExtIDs[n]))
func NewChainID(e interfaces.IEBEntry) interfaces.IHash {
	id := new(primitives.Hash)
	sum := sha256.New()
	for _, v := range e.ExternalIDs() {
		x := sha256.Sum256(v)
		sum.Write(x[:])
	}
	id.SetBytes(sum.Sum(nil))

	return id
}
Example #7
0
// InsertEntry inserts an entry
func (db *Overlay) InsertEntry(entry interfaces.IEBEntry) error {
	if entry == nil {
		return nil
	}

	//Entries are saved in buckets represented by their chainID for easy batch loading
	//They are also indexed in ENTRY bucket by their hash that points to their chainID
	//So they can be loaded in two load operations without needing to know their chainID

	batch := []interfaces.Record{}
	batch = append(batch, interfaces.Record{entry.GetChainID().Bytes(), entry.DatabasePrimaryIndex().Bytes(), entry})
	batch = append(batch, interfaces.Record{ENTRY, entry.DatabasePrimaryIndex().Bytes(), entry.GetChainIDHash()})

	return db.PutInBatch(batch)
}
Example #8
0
// AddEBEntry creates a new Entry Block Entry from the provided Factom Entry
// and adds it to the Entry Block Body.
func (e *EBlock) AddEBEntry(entry interfaces.IEBEntry) error {
	e.Body.EBEntries = append(e.Body.EBEntries, entry.GetHash())
	return nil
}
Example #9
0
func registerAnchorSigningKey(entry interfaces.IEBEntry, initial bool, height uint32, st *State, BlockChain string) error {
	extIDs := entry.ExternalIDs()
	if bytes.Compare([]byte{0x00}, extIDs[0]) != 0 ||
		!CheckExternalIDsLength(extIDs, []int{1, 15, 32, 1, 1, 20, 8, 33, 64}) {
		return errors.New("Identity Error Anchor Key: Invalid external ID length")
	}

	subChainID := entry.GetChainID()
	chainID := new(primitives.Hash)
	chainID.SetBytes(extIDs[2][:32])

	IdentityIndex := st.isIdentityChain(chainID)
	if IdentityIndex == -1 {
		return errors.New("Identity Error: This cannot happen. New Bitcoin Key to nonexistent identity")
	}

	if !st.Identities[IdentityIndex].ManagementChainID.IsSameAs(subChainID) {
		return errors.New("Identity Error: Entry was not placed in the correct management chain")
	}

	var ask []AnchorSigningKey
	var newAsk []AnchorSigningKey
	var oneAsk AnchorSigningKey

	ask = st.Identities[IdentityIndex].AnchorKeys
	newAsk = make([]AnchorSigningKey, len(ask)+1)

	oneAsk.BlockChain = BlockChain
	oneAsk.KeyLevel = extIDs[3][0]
	oneAsk.KeyType = extIDs[4][0]
	oneAsk.SigningKey = extIDs[5]

	contains := false
	for i := 0; i < len(ask); i++ {
		if ask[i].KeyLevel == oneAsk.KeyLevel &&
			strings.Compare(ask[i].BlockChain, oneAsk.BlockChain) == 0 {
			contains = true
			ask[i] = oneAsk
		} else {
			newAsk[i] = ask[i]
		}
	}

	newAsk[len(ask)] = oneAsk
	sigmsg, err := AppendExtIDs(extIDs, 0, 6)
	if err != nil {
		return err
	} else {
		// Verify Signature
		idKey := st.Identities[IdentityIndex].Key1
		if CheckSig(idKey, extIDs[7][1:33], sigmsg, extIDs[8]) {
			var key [20]byte
			if len(extIDs[5]) != 20 {
				return errors.New("New Anchor key for identity [" + chainID.String()[:10] + "] is invalid length")
			}

			dbase := st.GetAndLockDB()
			dblk, err := dbase.FetchDBlockByHeight(height)
			st.UnlockDB()
			if err == nil && dblk != nil && dblk.GetHeader().GetTimestamp().GetTimeSeconds() != 0 {
				if !CheckTimestamp(extIDs[6], dblk.GetHeader().GetTimestamp().GetTimeSeconds()) {
					return errors.New("New Anchor key for identity [" + chainID.String()[:10] + "] timestamp is too old")
				}
			} else {
				if !CheckTimestamp(extIDs[6], st.GetTimestamp().GetTimeSeconds()) {
					return errors.New("New Anchor key for identity [" + chainID.String()[:10] + "] timestamp is too old")
				}
			}

			if contains {
				st.Identities[IdentityIndex].AnchorKeys = ask
			} else {
				st.Identities[IdentityIndex].AnchorKeys = newAsk
			}
			// Add to admin block
			status := st.Identities[IdentityIndex].Status
			if !initial && statusIsFedOrAudit(status) && st.GetLeaderVM() == st.ComputeVMIndex(entry.GetChainID().Bytes()) {
				copy(key[:20], extIDs[5][:20])
				extIDs[5] = append(extIDs[5], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}...)
				key := primitives.NewHash(extIDs[5])
				msg := messages.NewChangeServerKeyMsg(st, chainID, constants.TYPE_ADD_BTC_ANCHOR_KEY, extIDs[3][0], extIDs[4][0], key)
				err := msg.(*messages.ChangeServerKeyMsg).Sign(st.serverPrivKey)
				if err != nil {
					return errors.New("New Block Signing key for identity [" + chainID.String()[:10] + "] Error: cannot sign msg")
				}
				st.InMsgQueue() <- msg
			}
		} else {
			return errors.New("New Anchor key for identity [" + chainID.String()[:10] + "] is invalid. Bad signiture")
		}
	}
	return nil
}
Example #10
0
func updateMatryoshkaHash(entry interfaces.IEBEntry, initial bool, height uint32, st *State) error {
	extIDs := entry.ExternalIDs()
	if len(extIDs) == 0 {
		return errors.New("Identity Error MHash: Invalid external ID length")
	}
	if bytes.Compare([]byte{0x00}, extIDs[0]) != 0 || // Version
		!CheckExternalIDsLength(extIDs, []int{1, 19, 32, 32, 8, 33, 64}) { // Signiture
		return errors.New("Identity Error MHash: Invalid external ID length")
	}
	chainID := new(primitives.Hash)
	chainID.SetBytes(extIDs[2][:32])
	subChainID := entry.GetChainID()

	IdentityIndex := st.isIdentityChain(chainID)
	if IdentityIndex == -1 {
		return errors.New("Identity Error: This cannot happen. New Matryoshka Hash to nonexistent identity")
	}

	if !st.Identities[IdentityIndex].ManagementChainID.IsSameAs(subChainID) {
		return errors.New("Identity Error: Entry was not placed in the correct management chain")
	}

	sigmsg, err := AppendExtIDs(extIDs, 0, 4)
	if err != nil {
		//log.Printfln("Identity Error:", err)
		return nil
	} else {
		// Verify Signature
		idKey := st.Identities[IdentityIndex].Key1
		if CheckSig(idKey, extIDs[5][1:33], sigmsg, extIDs[6]) {
			// Check MHash length
			if len(extIDs[3]) != 32 {
				return errors.New("New Matryoshka Hash for identity [" + chainID.String()[:10] + "] is invalid length")
			}

			dbase := st.GetAndLockDB()
			dblk, err := dbase.FetchDBlockByHeight(height)
			st.UnlockDB()
			if err == nil && dblk != nil && dblk.GetHeader().GetTimestamp().GetTimeSeconds() != 0 {
				if !CheckTimestamp(extIDs[4], dblk.GetHeader().GetTimestamp().GetTimeSeconds()) {
					return errors.New("New Matryoshka Hash for identity  [" + chainID.String()[:10] + "] timestamp is too old")
				}
			} else {
				if !CheckTimestamp(extIDs[4], st.GetTimestamp().GetTimeSeconds()) {
					return errors.New("New Matryoshka Hash for identity  [" + chainID.String()[:10] + "] timestamp is too old")
				}
			}

			mhash := primitives.NewHash(extIDs[3])
			st.Identities[IdentityIndex].MatryoshkaHash = mhash
			// Add to admin block
			status := st.Identities[IdentityIndex].Status
			if !initial && statusIsFedOrAudit(status) && st.GetLeaderVM() == st.ComputeVMIndex(entry.GetChainID().Bytes()) {
				//if st.LeaderPL.VMIndexFor(constants.ADMIN_CHAINID) == st.GetLeaderVM() {
				msg := messages.NewChangeServerKeyMsg(st, chainID, constants.TYPE_ADD_MATRYOSHKA, 0, 0, mhash)
				err := msg.(*messages.ChangeServerKeyMsg).Sign(st.serverPrivKey)
				if err != nil {
					return errors.New("New Block Signing key for identity [" + chainID.String()[:10] + "] Error: cannot sign msg")
				}
				//log.Printfln("DEBUG: MHash ChangeServer Message Sent")
				st.InMsgQueue() <- msg
				//}
			}
		} else {
			return errors.New("New Matryoshka Hash for identity [" + chainID.String()[:10] + "] is invalid. Bad signiture")
		}

	}
	return nil
}
Example #11
0
func registerBlockSigningKey(entry interfaces.IEBEntry, initial bool, height uint32, st *State) error {
	extIDs := entry.ExternalIDs()
	if len(extIDs) == 0 {
		return errors.New("Identity Error Block Signing Key: Invalid external ID length")
	}
	if bytes.Compare([]byte{0x00}, extIDs[0]) != 0 || // Version
		!CheckExternalIDsLength(extIDs, []int{1, 21, 32, 32, 8, 33, 64}) {
		return errors.New("Identity Error Block Signing Key: Invalid external ID length")
	}

	subChainID := entry.GetChainID()
	chainID := new(primitives.Hash)
	chainID.SetBytes(extIDs[2][:32])

	IdentityIndex := st.isIdentityChain(chainID)
	if IdentityIndex == -1 {
		return errors.New("Identity Error: This cannot happen. New block signing key to nonexistent identity")
	}

	if !st.Identities[IdentityIndex].ManagementChainID.IsSameAs(subChainID) {
		return errors.New("Identity Error: Entry was not placed in the correct management chain")
	}

	sigmsg, err := AppendExtIDs(extIDs, 0, 4)
	if err != nil {
		return err
	} else {
		//verify Signature
		idKey := st.Identities[IdentityIndex].Key1
		if CheckSig(idKey, extIDs[5][1:33], sigmsg, extIDs[6]) {
			// Check block key length
			if len(extIDs[3]) != 32 {
				return errors.New("New Block Signing key for identity [" + chainID.String()[:10] + "] is invalid length")
			}

			dbase := st.GetAndLockDB()
			dblk, err := dbase.FetchDBlockByHeight(height)
			st.UnlockDB()

			if err == nil && dblk != nil && dblk.GetHeader().GetTimestamp().GetTimeSeconds() != 0 {
				if !CheckTimestamp(extIDs[4], dblk.GetHeader().GetTimestamp().GetTimeSeconds()) {
					return errors.New("New Block Signing key for identity  [" + chainID.String()[:10] + "] timestamp is too old")
				}
			} else {
				if !CheckTimestamp(extIDs[4], st.GetTimestamp().GetTimeSeconds()) {
					return errors.New("New Block Signing key for identity  [" + chainID.String()[:10] + "] timestamp is too old")
				}
			}

			st.Identities[IdentityIndex].SigningKey = primitives.NewHash(extIDs[3])
			// Add to admin block
			status := st.Identities[IdentityIndex].Status
			if !initial && statusIsFedOrAudit(status) && st.GetLeaderVM() == st.ComputeVMIndex(entry.GetChainID().Bytes()) {
				key := primitives.NewHash(extIDs[3])
				msg := messages.NewChangeServerKeyMsg(st, chainID, constants.TYPE_ADD_FED_SERVER_KEY, 0, 0, key)
				err := msg.(*messages.ChangeServerKeyMsg).Sign(st.serverPrivKey)
				if err != nil {
					return errors.New("New Block Signing key for identity [" + chainID.String()[:10] + "] Error: cannot sign msg")
				}
				st.InMsgQueue() <- msg
			}
		} else {
			return errors.New("New Block Signing key for identity [" + chainID.String()[:10] + "] is invalid. Bad signiture")
		}
	}
	return nil
}
Example #12
0
func LoadIdentityByEntry(ent interfaces.IEBEntry, st *State, height uint32, initial bool) {
	if ent == nil {
		return
	}
	hs := ent.GetChainID().String()
	cid := ent.GetChainID()
	if st.isIdentityChain(cid) == -1 {
		if st.isAuthorityChain(cid) != -1 {
			// The authority exists, but the Identity does not. This could be an issue if a
			// server changes their key as we would not notice the change
		}
		return
	}
	if hs[0:60] != "000000000000000000000000000000000000000000000000000000000000" { //ignore minute markers
		if len(ent.ExternalIDs()) > 1 {
			if string(ent.ExternalIDs()[1]) == "Register Server Management" {
				registerIdentityAsServer(ent, height, st)
			} else if string(ent.ExternalIDs()[1]) == "New Block Signing Key" {
				if len(ent.ExternalIDs()) == 7 {
					registerBlockSigningKey(ent, initial, height, st)
				}
			} else if string(ent.ExternalIDs()[1]) == "New Bitcoin Key" {
				if len(ent.ExternalIDs()) == 9 {
					registerAnchorSigningKey(ent, initial, height, st, "BTC")
				}
			} else if string(ent.ExternalIDs()[1]) == "New Matryoshka Hash" {
				if len(ent.ExternalIDs()) == 7 {
					updateMatryoshkaHash(ent, initial, height, st)
				}
			} else if len(ent.ExternalIDs()) > 1 && string(ent.ExternalIDs()[1]) == "Identity Chain" {
				addIdentity(ent, height, st)
			} else if len(ent.ExternalIDs()) > 1 && string(ent.ExternalIDs()[1]) == "Server Management" {
				if len(ent.ExternalIDs()) == 4 {
					updateManagementKey(ent, height, st)
				}
			}
		}
	}
}