// ProposeChannel is called to propose a new channel. It creates and signs an
// OpeningTx, sends it to the Counterparty and saves it in a new Channel.
func (a *CallerAPI) ProposeChannel(
	channelId string,
	state []byte,
	myPubkey []byte,
	theirPubkey []byte,
	holdPeriod uint64,
) (*core.Channel, error) {
	ch := &core.Channel{}
	err := a.DB.Update(func(tx *bolt.Tx) error {
		acct, err := access.GetAccount(tx, myPubkey)
		if err != nil {
			return err
		}

		cpt, err := access.GetCounterparty(tx, theirPubkey)
		if err != nil {
			return err
		}

		otx, err := acct.NewOpeningTx(channelId, cpt, state, holdPeriod)
		if err != nil {
			return err
		}

		ev, err := core.SerializeOpeningTx(otx)
		if err != nil {
			return err
		}

		acct.AppendSignature(ev)

		ch, err = core.NewChannel(ev, otx, acct, cpt)
		if err != nil {
			return err
		}

		err = a.CounterpartyClient.AddChannel(ev, cpt.Address)
		if err != nil {
			return err
		}

		err = access.SetChannel(tx, ch)
		if err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return ch, nil
}
func (a *CounterpartyAPI) AddChannel(ev *wire.Envelope) error {
	var err error

	otx := &wire.OpeningTx{}
	err = proto.Unmarshal(ev.Payload, otx)
	if err != nil {
		return err
	}

	acct := &core.Account{}
	cpt := &core.Counterparty{}
	err = a.DB.Update(func(tx *bolt.Tx) error {
		_, nilErr := access.GetChannel(tx, otx.ChannelId)
		if nilErr == nil {
			return errors.New("channel already exists")
		}
		_, ok := nilErr.(*access.NilError)
		if !ok {
			return err
		}

		cpt, err = access.GetCounterparty(tx, otx.Pubkeys[0])
		if err != nil {
			return err
		}

		acct, err = access.GetAccount(tx, otx.Pubkeys[1])
		if err != nil {
			return err
		}

		err = acct.CheckOpeningTx(ev, cpt)
		if err != nil {
			return err
		}

		ch, err := core.NewChannel(ev, otx, acct, cpt)
		if err != nil {
			return err
		}

		access.SetChannel(tx, ch)
		if err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return err
	}

	return nil
}