I did not quite understand why we need to generate a label for the ipv6 prefix.
Once packet reaches the PE, cannot it not just look at the ipv6 address and route the packet?
But it does not seem to work unless you send ipv6 label via bgp.
A single label (the IPv4 transport one) would mean the packet is destined to the remote PE, which is not true. Thus you need a label for the customer, regardless if it's in GRT or VRF.
The subject line says 6PE (IPv6 transported over an MPLS network using labels, or what I'd call a "layer 2.5 abstraction"), which is different than 6vPE (IPv6 VRFs transported over an MPLS network using labels, or what I'd call "vpnv6 using MPLS labels"). Regardless, in thinking through this, you would need an inner label that doesn't get popped via PHP. That way the packet can travel from the penultimate hop to the egress PE node with (at least) one label, so that the final PE can pop the label and forward it appropriately.
Without that second label, PHP would strip the outer label and the penultimate P node would attempt to forward the packet over an IPv4-only link. I don't think there's a way to disable PHP upon initial label imposition, and there'd be no way to signal 6PE to get an explicit null label (i.e. to get different behavior than another protocol), so the only way to ensure at least one label from P[-1] to PE is an inner "vpn-like" label.
(The paragraphs above are me just thinking aloud, and are not fact-checked in any way...)
I think the only reason for having 2 labels is that the PHP device needs to be ipv6 aware and we are trying to avoid this. I cannot think off any other reason.
Else it is easy to just have the ldp label and do normal forwarding on the P router (if it is ipv6 aware)