user38469: (Here is finally a solution).
I'm using the following code on a ATtiny45 to assign an interrupt to a button press (pin #7, PB2, INT0). However the LED doesn't blink when the button is pressed, as if the interrupt is not working. Why?
Note: I'd like to use the least power when no interrupt happens, to have a current in the order of magnitude of ~ 1 µA, to run from batteries for years.
#include <avr/sleep.h>

void setup() 
{
  pinMode(4, OUTPUT);  // LED
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);      // pin #7 = PB2
  digitalWrite(4, HIGH); delay(100); digitalWrite(4, LOW);  // LED blink, working here
}

void wake()
{
  sleep_disable(); 
  detachInterrupt(0); 
  digitalWrite(4, HIGH);  // LED not working here when pressing the button
} 

void loop()
{
  sleep_enable();
  ADCSRA = 0;  
  attachInterrupt(0, wake, CHANGE);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_cpu(); 
}

Note: 

I'm using Arduino IDE with damellis' attiny, I also tried with Spence Konde's ATtinyCore but it's the same
In my real code, I have 3 buttons, on pin #5, #6, #7, so eventually I'd like to have interrupts for all these three pins.
I've read https://gammon.com.au/forum/?id=11497 but using noInterrupts() / interrupts() did not change anything in my case.
I've tried "Sketch J" from https://gammon.com.au/forum/?id=11497 but EIFR = bit (INTF0); gives an error: 'EIFR' was not declared in this scope (I'm compiling from Arduino IDE); probably this works on an ATmega but not ATtiny.


Edit: Here is a working code of deep sleep, with an interrupt when the pin #5 (PB0) changes...
#include <avr/interrupt.h>
#include <avr/sleep.h>

ISR(PCINT0_vect) {
  if (digitalRead(0) == LOW)
    digitalWrite(4, HIGH);
  else
    digitalWrite(4, LOW);
}

void setup() {  
  pinMode(4,OUTPUT); // LED
  pinMode(0,INPUT_PULLUP);
  pinMode(1,INPUT_PULLUP);
  pinMode(2,INPUT_PULLUP);
  ADCSRA = 0; // ADC disabled
  GIMSK = 0b00100000;  // General Interrupt Mask Register, / Bit 5 – PCIE: Pin Change Interrupt Enable / When the PCIE bit is set (one) and the I-bit in the Status Register (SREG) is set (one), pin change interrupt is enabled. Any change on any enabled PCINT[5:0] pin will cause an interrupt. The corresponding interrupt of Pin Change Interrupt Request is executed from the PCI Interrupt Vector. PCINT[5:0] pins are enabled individually by the PCMSK0 Register. / see https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
  PCMSK = 0b00000111;  // Pin-change interrupt for PB0, PB1, PB2
} 

void loop() {
  sleep_enable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_cpu(); 
}

...but for an unknown reason, if I add this code:
ISR(PCINT1_vect) {
  if (digitalRead(1) == LOW)
    digitalWrite(4, HIGH);
  else
    digitalWrite(4, LOW);
}

the pin-change interrupt for PB0 still works (PCINT0), but not the interrupt for PB1 (PCINT1). Why?

user7508: Look at the datasheet of the ATtiny45. In the section “Sleep Modes”,
there is a table that lists the wake-up sources available for each sleep
mode. For the mode “power-down”, INT0 is listed as a possible wake-up
source, but there is a small footnote:

For INT0, only level interrupt.

This means that the CHANGE mode you are trying to use will not wake-up
the MCU out of power-down. You have to instead
attachInterrupt(0, wake, LOW);


In my real code, I have 3 buttons, on pin #5, #6, #7, so eventually
  I'd like to have interrupts for all these three pins.

You may then have to look into the “pin-change” interrupt. This is
something different from the INT0 you are using here, and is not
generally supported by the Arduino core. You will have to either get
some pin-change-interrupt library, or work with no library using the
information from the datasheet (not that hard). Pin-change interrupt is
also a wake-up source for power-down.

Edit: Answering extra questions from comments.

How did you know that "only level interrupt" means only "LOW"?

The Arduino documentation states that the mode
parameter of attachInterrupt() can be either LOW, CHANGE, RISING
or FALLING. A few boards also support HIGH, but the ATtinies are not
among them. A “level” can be either LOW or HIGH, whereas CHANGE,
RISING and FALLING are “edges”.
This is corroborated by the ATtiny45 datasheet: “The INT0
interrupts can be triggered by a falling or rising edge or a low level.”

Is pin-change interrupt PCINT?

Yes.

why do you think it isn't supported by the Arduino core?

The attachInterrupt() API only really makes sense for INT0, INT1,
etc... not for PCINT. You can also look at the source code.

Isn't it standard to interrupt when a pin changes states?

If you wish, you can configure INT0 to interrupt on a rising edge, a
falling edge, or any logical change. But this uses an edge-detection
logic which relies on the main clock, and thus does not work in
power-down mode.
For more details on INT0 vs. PCINT, their differences, and how to use
them, please refer to the datasheet, specifically to the “External
Interrupts” section I linked to above.

Addendum: Extra question:

why it doesn't work [with ISR(PCINT1_vect) {...}]?

Gcc tells me “warning: ‘PCINT1_vect’ appears to be a misspelled
signal handler”. And indeed, there is no such interrupt vector on the
ATtiny45: there is only PCINT0_vect, and this interrupt is shared by
all the pins that can generate a pin change interrupt. If you want to
know which pin triggered the interrupt, you will have to figure that out
within the interrupt handler itself.
This is the single point that makes the PCINTs trickier to work with
than INT0 and co.: each PCINT interrupt is shared by a group of pins. On
the ATtiny45, there is only one such group, and PCINT0_vect is the
only interrupt handler. Larger AVRs have more groups (3 on the
Uno/ATmega328P), and PCINT1_vect makes sense on them.
Also beware of the somewhat confusing naming scheme. Avr-libc defines
some macros PCINTn, where n is a number. These macros expand to bit
numbers, and are meant to be used in code like this:
PCMSK = _BV(PCINT0)   // sense changes in pin PCINT0 = PB0...
      | _BV(PCINT1)   // and PCINT1 = PB1...
      | _BV(PCINT2);  // and PCINT2 = PB2

In these macros, the number n identifies an individual pin. Avr-libc
also defines the macros PCINTm_vect for defining interrupt handlers.
In these macros, the number m identifies a pin group.

38469: <p><em>(<a href="https://arduino.stackexchange.com/questions/70284/how-to-deep-sleep-attiny-atmega-to-run-for-years-with-batteries-but-still-dete/70289#70289">Here</a> is finally a solution)</em>.</p>

<p>I'm using the following code on a ATtiny45 to <strong>assign an interrupt to a button press</strong> (pin #7, PB2, INT0). However the LED doesn't blink when the button is pressed, as if the interrupt is not working. <strong>Why?</strong></p>

<p>Note: I'd like to use the least power when no interrupt happens, to <a href="https://arduino.stackexchange.com/questions/70284/how-to-deep-sleep-attiny-atmega-to-run-for-years-with-batteries-but-still-dete/70296#70296">have a current in the order of magnitude of ~ 1 µA, to run from batteries for years</a>.</p>

<pre><code>#include &lt;avr/sleep.h&gt;

void setup() 
{
  pinMode(4, OUTPUT);  // LED
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);      // pin #7 = PB2
  digitalWrite(4, HIGH); delay(100); digitalWrite(4, LOW);  // LED blink, working here
}

void wake()
{
  sleep_disable(); 
  detachInterrupt(0); 
  digitalWrite(4, HIGH);  // LED not working here when pressing the button
} 

void loop()
{
  sleep_enable();
  ADCSRA = 0;  
  attachInterrupt(0, wake, CHANGE);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_cpu(); 
}
</code></pre>

<p>Note: </p>

<ul>
<li><p>I'm using Arduino IDE with <a href="https://github.com/damellis/attiny" rel="nofollow noreferrer">damellis' attiny</a>, I also tried with Spence Konde's ATtinyCore but it's the same</p></li>
<li><p>In my real code, I have 3 buttons, on pin #5, #6, #7, so eventually I'd like to have interrupts for all these three pins.</p></li>
<li><p>I've read <a href="https://gammon.com.au/forum/?id=11497" rel="nofollow noreferrer">https://gammon.com.au/forum/?id=11497</a> but using <code>noInterrupts()</code> / <code>interrupts()</code> did not change anything in my case.</p></li>
<li><p>I've tried "Sketch J" from <a href="https://gammon.com.au/forum/?id=11497" rel="nofollow noreferrer">https://gammon.com.au/forum/?id=11497</a> but <code>EIFR = bit (INTF0);</code> gives an <code>error: 'EIFR' was not declared in this scope</code> (I'm compiling from Arduino IDE); probably this works on an ATmega but not ATtiny.</p></li>
</ul>

<hr>

<p><strong>Edit: Here is a working code of deep sleep, with an interrupt when the pin #5 (PB0) changes...</strong></p>

<pre><code>#include &lt;avr/interrupt.h&gt;
#include &lt;avr/sleep.h&gt;

ISR(PCINT0_vect) {
  if (digitalRead(0) == LOW)
    digitalWrite(4, HIGH);
  else
    digitalWrite(4, LOW);
}

void setup() {  
  pinMode(4,OUTPUT); // LED
  pinMode(0,INPUT_PULLUP);
  pinMode(1,INPUT_PULLUP);
  pinMode(2,INPUT_PULLUP);
  ADCSRA = 0; // ADC disabled
  GIMSK = 0b00100000;  // General Interrupt Mask Register, / Bit 5 – PCIE: Pin Change Interrupt Enable / When the PCIE bit is set (one) and the I-bit in the Status Register (SREG) is set (one), pin change interrupt is enabled. Any change on any enabled PCINT[5:0] pin will cause an interrupt. The corresponding interrupt of Pin Change Interrupt Request is executed from the PCI Interrupt Vector. PCINT[5:0] pins are enabled individually by the PCMSK0 Register. / see https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
  PCMSK = 0b00000111;  // Pin-change interrupt for PB0, PB1, PB2
} 

void loop() {
  sleep_enable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_cpu(); 
}
</code></pre>

<p><strong>...but for an unknown reason, if I add this code:</strong></p>

<pre><code>ISR(PCINT1_vect) {
  if (digitalRead(1) == LOW)
    digitalWrite(4, HIGH);
  else
    digitalWrite(4, LOW);
}
</code></pre>

<p>the pin-change interrupt for PB0 still works (PCINT0), but not the interrupt for PB1 (PCINT1). Why?</p>
 7508: <p>Look at the datasheet of the ATtiny45. In the section “Sleep Modes”,
there is a table that lists the wake-up sources available for each sleep
mode. For the mode “power-down”, INT0 is listed as a possible wake-up
source, but there is a small footnote:</p>

<blockquote>
  <p>For INT0, only level interrupt.</p>
</blockquote>

<p>This means that the <code>CHANGE</code> mode you are trying to use will not wake-up
the MCU out of power-down. You have to instead</p>

<pre class="lang-cpp prettyprint-override"><code>attachInterrupt(0, wake, LOW);
</code></pre>

<blockquote>
  <p>In my real code, I have 3 buttons, on pin #5, #6, #7, so eventually
  I'd like to have interrupts for all these three pins.</p>
</blockquote>

<p>You may then have to look into the “pin-change” interrupt. This is
something different from the INT0 you are using here, and is not
generally supported by the Arduino core. You will have to either get
some pin-change-interrupt library, or work with no library using the
information from the datasheet (not that hard). Pin-change interrupt is
also a wake-up source for power-down.</p>

<hr>

<p><strong>Edit</strong>: Answering extra questions from comments.</p>

<blockquote>
  <p>How did you know that "only level interrupt" means only "LOW"?</p>
</blockquote>

<p>The <a href="https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/#_parameters" rel="nofollow noreferrer">Arduino documentation</a> states that the <code>mode</code>
parameter of <code>attachInterrupt()</code> can be either <code>LOW</code>, <code>CHANGE</code>, <code>RISING</code>
or <code>FALLING</code>. A few boards also support <code>HIGH</code>, but the ATtinies are not
among them. A “level” can be either <code>LOW</code> or <code>HIGH</code>, whereas <code>CHANGE</code>,
<code>RISING</code> and <code>FALLING</code> are “edges”.</p>

<p>This is corroborated by the <a href="https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf#G1.1738372" rel="nofollow noreferrer">ATtiny45 datasheet</a>: “The INT0
interrupts can be triggered by a falling or rising edge or a low level.”</p>

<blockquote>
  <p>Is pin-change interrupt <code>PCINT</code>?</p>
</blockquote>

<p>Yes.</p>

<blockquote>
  <p>why do you think it isn't supported by the Arduino core?</p>
</blockquote>

<p>The <code>attachInterrupt()</code> API only really makes sense for INT0, INT1,
etc... not for PCINT. You can also look at <a href="https://github.com/arduino/ArduinoCore-avr/blob/1.8.1/cores/arduino/WInterrupts.c#L69" rel="nofollow noreferrer">the source code</a>.</p>

<blockquote>
  <p>Isn't it standard to interrupt when a pin changes states?</p>
</blockquote>

<p>If you wish, you can configure INT0 to interrupt on a rising edge, a
falling edge, or any logical change. But this uses an edge-detection
logic which relies on the main clock, and thus does not work in
power-down mode.</p>

<p>For more details on INT0 vs. PCINT, their differences, and how to use
them, please refer to the datasheet, specifically to the “External
Interrupts” section I linked to above.</p>

<hr>

<p><strong>Addendum</strong>: Extra question:</p>

<blockquote>
  <p>why it doesn't work [with <code>ISR(PCINT1_vect) {...}</code>]?</p>
</blockquote>

<p>Gcc tells me “<strong>warning: ‘PCINT1_vect’</strong> appears to be a misspelled
signal handler”. And indeed, there is no such interrupt vector on the
ATtiny45: there is only PCINT0_vect, and this interrupt is shared by
all the pins that can generate a pin change interrupt. If you want to
know which pin triggered the interrupt, you will have to figure that out
within the interrupt handler itself.</p>

<p>This is the single point that makes the PCINTs trickier to work with
than INT0 and co.: each PCINT interrupt is shared by a group of pins. On
the ATtiny45, there is only one such group, and <code>PCINT0_vect</code> is the
only interrupt handler. Larger AVRs have more groups (3 on the
Uno/ATmega328P), and <code>PCINT1_vect</code> makes sense on them.</p>

<p>Also beware of the somewhat confusing naming scheme. Avr-libc defines
some macros <code>PCINTn</code>, where <code>n</code> is a number. These macros expand to bit
numbers, and are meant to be used in code like this:</p>

<pre class="lang-cpp prettyprint-override"><code>PCMSK = _BV(PCINT0)   // sense changes in pin PCINT0 = PB0...
      | _BV(PCINT1)   // and PCINT1 = PB1...
      | _BV(PCINT2);  // and PCINT2 = PB2
</code></pre>

<p>In these macros, the number <code>n</code> identifies an <em>individual pin</em>. Avr-libc
also defines the macros <code>PCINTm_vect</code> for defining interrupt handlers.
In these macros, the number <code>m</code> identifies a <em>pin group</em>.</p>
